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.menueadd Lock RC
rclock.title Lock Remote Control rclock.title Lock Remote Control
rclock.unlockmsg Remote control reactivated. 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_ac3 record AC3 streams
recordingmenu.apids_alt record alternative streams recordingmenu.apids_alt record alternative streams
recordingmenu.apids Audio streams recordingmenu.apids Audio streams

View File

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

View File

@@ -4,12 +4,11 @@
Copyright (C) 2001 Steffen Hehn 'McClean' Copyright (C) 2001 Steffen Hehn 'McClean'
Copyright (C) 2011 CoolStream International Ltd Copyright (C) 2011 CoolStream International Ltd
License: GPL License: GPLv2
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation;
(at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -50,7 +49,6 @@
#include <gui/nfs.h> #include <gui/nfs.h>
#include <driver/record.h> #include <driver/record.h>
#include <ca_cs.h>
#include <zapit/capmt.h> #include <zapit/capmt.h>
#include <zapit/channel.h> #include <zapit/channel.h>
#include <zapit/getservices.h> #include <zapit/getservices.h>
@@ -64,7 +62,6 @@
*/ */
extern CRemoteControl * g_RemoteControl; /* neutrino.cpp */ extern CRemoteControl * g_RemoteControl; /* neutrino.cpp */
t_channel_id rec_channel_id;
bool sectionsd_getActualEPGServiceKey(const t_channel_id uniqueServiceKey, CEPGData * epgdata); bool sectionsd_getActualEPGServiceKey(const t_channel_id uniqueServiceKey, CEPGData * epgdata);
bool sectionsd_getEPGidShort(event_id_t epgID, CShortEPGData * 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); usleep(100000);
} }
record_error_msg_t CRecordInstance::Start(CZapitChannel * channel /*, APIDList &apid_list*/) record_error_msg_t CRecordInstance::Start(CZapitChannel * channel)
{ {
int fd; int fd;
std::string tsfile; std::string tsfile;
@@ -142,7 +139,7 @@ record_error_msg_t CRecordInstance::Start(CZapitChannel * channel /*, APIDList &
time_t msg_start_time = time(0); time_t msg_start_time = time(0);
CHintBox hintBox(LOCALE_MESSAGEBOX_INFO, g_Locale->getText(LOCALE_RECORDING_START)); CHintBox hintBox(LOCALE_MESSAGEBOX_INFO, g_Locale->getText(LOCALE_RECORDING_START));
hintBox.paint(); hintBox.paint();
tsfile = std::string(filename) + ".ts"; tsfile = std::string(filename) + ".ts";
printf("%s: file %s vpid %x apid %x\n", __FUNCTION__, tsfile.c_str(), allpids.PIDs.vpid, apids[0]); printf("%s: file %s vpid %x apid %x\n", __FUNCTION__, tsfile.c_str(), allpids.PIDs.vpid, apids[0]);
@@ -193,11 +190,6 @@ record_error_msg_t CRecordInstance::Start(CZapitChannel * channel /*, APIDList &
CCamManager::getInstance()->Start(channel->getChannelID(), CCamManager::RECORD); 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); //CVFD::getInstance()->ShowIcon(VFD_ICON_CAM1, true);
WaitRecMsg(msg_start_time, 2); WaitRecMsg(msg_start_time, 2);
hintBox.hide(); hintBox.hide();
@@ -219,7 +211,7 @@ bool CRecordInstance::Stop(bool remove_event)
time_t end_time = time(0); time_t end_time = time(0);
recMovieInfo->length = (int) round((double) (end_time - start_time) / (double) 60); recMovieInfo->length = (int) round((double) (end_time - start_time) / (double) 60);
CHintBox hintBox(LOCALE_MESSAGEBOX_INFO, rec_stop_msg.c_str()); CHintBox hintBox(LOCALE_MESSAGEBOX_INFO, rec_stop_msg.c_str());
hintBox.paint(); hintBox.paint();
@@ -609,7 +601,7 @@ record_error_msg_t CRecordInstance::MakeFileName(CZapitChannel * channel)
strncat(filename,"/",FILENAMEBUFFERSIZE - strlen(filename)); strncat(filename,"/",FILENAMEBUFFERSIZE - strlen(filename));
else else
perror("[vcrcontrol] mkdir"); perror("[vcrcontrol] mkdir");
} else } else
perror("[vcrcontrol] stat"); perror("[vcrcontrol] stat");
} else } else
// directory exists // directory exists
@@ -652,7 +644,9 @@ void CRecordInstance::GetRecordString(std::string &str)
str = "Unknown channel : " + GetEpgTitle(); str = "Unknown channel : " + GetEpgTitle();
return; 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) CRecordInstance * CRecordManager::FindInstance(t_channel_id channel_id)
{ {
recmap_iterator_t it = recmap.find(channel_id); for (recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++) {
if(it != recmap.end()) if (it->second->GetChannelId() == channel_id)
return it->second; 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; return NULL;
} }
@@ -742,7 +746,7 @@ int CRecordManager::GetRecordMode(const t_channel_id channel_id)
return RECMODE_REC_TSHIFT; return RECMODE_REC_TSHIFT;
else else
return RECMODE_OFF; return RECMODE_OFF;
}else } else
{ {
if (IsTimeshift(channel_id)) if (IsTimeshift(channel_id))
return RECMODE_TSHIFT; return RECMODE_TSHIFT;
@@ -771,7 +775,7 @@ bool CRecordManager::Record(const t_channel_id channel_id, const char * dir, boo
} }
eventinfo.apids = TIMERD_APIDS_CONF; eventinfo.apids = TIMERD_APIDS_CONF;
eventinfo.recordingDir[0] = 0; eventinfo.recordingDir[0] = 0;
return Record(&eventinfo, dir, timeshift); return Record(&eventinfo, dir, timeshift);
} }
@@ -797,24 +801,25 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
RunStartScript(); RunStartScript();
mutex.lock(); mutex.lock();
recmap_iterator_t it = recmap.find(eventinfo->channel_id); #if 0
if(it != recmap.end()) { inst = FindInstance(eventinfo->channel_id);
//inst = it->second; if(inst) {
if(direct_record) { if(direct_record) {
error_msg = RECORD_BUSY; error_msg = RECORD_BUSY;
} else { } else {
//nextmap.push_back((CTimerd::RecordingInfo *)eventinfo);
CTimerd::RecordingInfo * evt = new CTimerd::RecordingInfo(*eventinfo); CTimerd::RecordingInfo * evt = new CTimerd::RecordingInfo(*eventinfo);
printf("%s add %llx : %s to pending\n", __FUNCTION__, evt->channel_id, evt->epgTitle); printf("%s add %llx : %s to pending\n", __FUNCTION__, evt->channel_id, evt->epgTitle);
nextmap.push_back((CTimerd::RecordingInfo *)evt); nextmap.push_back((CTimerd::RecordingInfo *)evt);
} }
} else if(recmap.size() < RECORD_MAX_COUNT) { } else
#if 1//FIXME test #endif
if(recmap.size() < RECORD_MAX_COUNT) {
CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(eventinfo->channel_id); CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(eventinfo->channel_id);
CFrontend * frontend = CFEManager::getInstance()->allocateFE(channel); CFrontend * frontend = CFEManager::getInstance()->allocateFE(channel);
int mode = channel->getServiceType() != ST_DIGITAL_RADIO_SOUND_SERVICE ? int mode = channel->getServiceType() != ST_DIGITAL_RADIO_SOUND_SERVICE ?
NeutrinoMessages::mode_tv : NeutrinoMessages::mode_radio; NeutrinoMessages::mode_tv : NeutrinoMessages::mode_radio;
#endif
if(frontend && CutBackNeutrino(eventinfo->channel_id, mode)) { if(frontend && CutBackNeutrino(eventinfo->channel_id, mode)) {
std::string newdir; std::string newdir;
if(dir && strlen(dir)) if(dir && strlen(dir))
@@ -824,21 +829,18 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
else else
newdir = Directory; newdir = Directory;
if (inst == NULL) inst = new CRecordInstance(eventinfo, newdir, timeshift, StreamVTxtPid, StreamPmtPid);
inst = new CRecordInstance(eventinfo, newdir, timeshift, StreamVTxtPid, StreamPmtPid);
inst->frontend = frontend; inst->frontend = frontend;
error_msg = inst->Record(); error_msg = inst->Record();
if(error_msg == RECORD_OK) { 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) if(timeshift)
autoshift = true; autoshift = true;
// mimic old behavior for start/stop menu option chooser, still actual ? // mimic old behavior for start/stop menu option chooser, still actual ?
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); 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; recordingstatus = 1;
rec_channel_id = live_channel_id;//FIXME
}
} else { } else {
delete inst; delete inst;
} }
@@ -867,7 +869,7 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons
LOCALE_STREAMING_WRITE_ERROR )); // UTF-8 LOCALE_STREAMING_WRITE_ERROR )); // UTF-8
return false; return false;
} }
return true; return true;
} }
@@ -914,6 +916,7 @@ bool CRecordManager::CheckRecording(const CTimerd::RecordingInfo * const eventin
return true; return true;
} }
/* FIXME no check for multi-tuner */
void CRecordManager::StartNextRecording() void CRecordManager::StartNextRecording()
{ {
CTimerd::RecordingInfo * eventinfo = NULL; CTimerd::RecordingInfo * eventinfo = NULL;
@@ -972,13 +975,14 @@ bool CRecordManager::TimeshiftOnly()
return (autoshift && (count == 1)); return (autoshift && (count == 1));
} }
/* FIXME no check for multi-tuner */
bool CRecordManager::SameTransponder(const t_channel_id channel_id) bool CRecordManager::SameTransponder(const t_channel_id channel_id)
{ {
bool same = true; bool same = true;
mutex.lock(); mutex.lock();
int count = recmap.size(); int count = recmap.size();
if(count) { if(count) {
if(autoshift && count == 1) if(autoshift && count == 1)
same = true; same = true;
else { else {
recmap_iterator_t fit = recmap.begin(); recmap_iterator_t fit = recmap.begin();
@@ -990,52 +994,54 @@ bool CRecordManager::SameTransponder(const t_channel_id channel_id)
return same; 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) bool CRecordManager::Stop(const t_channel_id channel_id)
{ {
printf("%s: %llx\n", __FUNCTION__, channel_id); printf("%s: %llx\n", __FUNCTION__, channel_id);
mutex.lock(); mutex.lock();
/* FIXME stop all ? show list ? */
CRecordInstance * inst = FindInstance(channel_id); CRecordInstance * inst = FindInstance(channel_id);
if(inst != NULL) { if(inst != NULL)
inst->Stop(); StopInstance(inst);
recmap.erase(channel_id); else
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
printf("%s: channel %llx not recording\n", __FUNCTION__, channel_id); printf("%s: channel %llx not recording\n", __FUNCTION__, channel_id);
mutex.unlock(); mutex.unlock();
StopPostProcess(); StopPostProcess();
return (inst != NULL); return (inst != NULL);
} }
bool CRecordManager::Stop(const CTimerd::RecordingStopInfo * recinfo) bool CRecordManager::Stop(const CTimerd::RecordingStopInfo * recinfo)
{ {
bool ret = false; bool ret = false;
printf("%s: eventID %d channel_id %llx\n", __FUNCTION__, recinfo->eventID, recinfo->channel_id); printf("%s: eventID %d channel_id %llx\n", __FUNCTION__, recinfo->eventID, recinfo->channel_id);
mutex.lock(); 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()) { if(inst != NULL && recinfo->eventID == inst->GetRecordingId()) {
inst->Stop(false); StopInstance(inst, false);
recmap.erase(recinfo->channel_id);
if(inst->Timeshift())
autoshift = false;
delete inst;
ret = true; ret = true;
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
if(recinfo->channel_id == live_channel_id)
recordingstatus = 0;
} else { } else {
for(nextmap_iterator_t it = nextmap.begin(); it != nextmap.end(); it++) { for(nextmap_iterator_t it = nextmap.begin(); it != nextmap.end(); it++) {
if((*it)->eventID == recinfo->eventID) { if((*it)->eventID == recinfo->eventID) {
@@ -1054,7 +1060,7 @@ bool CRecordManager::Stop(const CTimerd::RecordingStopInfo * recinfo)
mutex.unlock(); mutex.unlock();
StopPostProcess(); StopPostProcess();
return ret; return ret;
} }
@@ -1111,12 +1117,11 @@ bool CRecordManager::IsTimeshift(t_channel_id channel_id)
ret = true; ret = true;
else else
ret = false; ret = false;
}else } else
{ {
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++) for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
{ {
inst = it->second; if(it->second->tshift_mode)
if(inst && inst->tshift_mode)
{ {
mutex.unlock(); mutex.unlock();
return true; return true;
@@ -1129,14 +1134,11 @@ bool CRecordManager::IsTimeshift(t_channel_id channel_id)
void CRecordManager::SetTimeshiftMode(CRecordInstance * inst, int mode) void CRecordManager::SetTimeshiftMode(CRecordInstance * inst, int mode)
{ {
CRecordInstance * tmp_inst;
mutex.lock(); mutex.lock();
/* reset all instances mode ? */
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++) for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++)
{ it->second->tshift_mode = TSHIFT_MODE_OFF;
tmp_inst = it->second;
if (tmp_inst)
tmp_inst->tshift_mode = TSHIFT_MODE_OFF;
}
mutex.unlock(); mutex.unlock();
if (inst) if (inst)
inst->tshift_mode = mode; inst->tshift_mode = mode;
@@ -1154,13 +1156,13 @@ void CRecordManager::StartTimeshift()
tmode = "ptimeshift"; // already recording, pause tmode = "ptimeshift"; // already recording, pause
if(GetRecordMode(live_channel_id) == RECMODE_TSHIFT) if(GetRecordMode(live_channel_id) == RECMODE_TSHIFT)
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PAUSE); SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PAUSE);
}else } else
{ {
if(g_settings.temp_timeshift) if(g_settings.temp_timeshift)
{ {
res = StartAutoRecord(); res = StartAutoRecord();
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_TEMPORAER); SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_TEMPORAER);
}else } else
{ {
res = Record(live_channel_id); res = Record(live_channel_id);
SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PERMANET); SetTimeshiftMode(FindInstance(live_channel_id), TSHIFT_MODE_PERMANET);
@@ -1186,7 +1188,7 @@ int CRecordManager::exec(CMenuTarget* parent, const std::string & actionKey )
char rec_msg[256]; char rec_msg[256];
char rec_msg1[256]; char rec_msg1[256];
int records = recmap.size(); int records = recmap.size();
snprintf(rec_msg1, sizeof(rec_msg1)-1, "%s", g_Locale->getText(LOCALE_RECORDINGMENU_MULTIMENU_ASK_STOP_ALL)); snprintf(rec_msg1, sizeof(rec_msg1)-1, "%s", g_Locale->getText(LOCALE_RECORDINGMENU_MULTIMENU_ASK_STOP_ALL));
snprintf(rec_msg, sizeof(rec_msg)-1, rec_msg1, records); snprintf(rec_msg, sizeof(rec_msg)-1, rec_msg1, records);
if(ShowMsgUTF(LOCALE_SHUTDOWN_RECODING_QUERY, rec_msg, if(ShowMsgUTF(LOCALE_SHUTDOWN_RECODING_QUERY, rec_msg,
@@ -1198,12 +1200,13 @@ int CRecordManager::exec(CMenuTarget* parent, const std::string & actionKey )
mutex.lock(); mutex.lock();
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++) 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; CRecordInstance * inst = it->second;
t_channel_id channel_id = inst->GetChannelId();
snprintf(rec_msg, sizeof(rec_msg)-1, rec_msg1, records-i, records); snprintf(rec_msg, sizeof(rec_msg)-1, rec_msg1, records-i, records);
inst->SetStopMessage(rec_msg); inst->SetStopMessage(rec_msg);
printf("CRecordManager::exec(ExitAll line %d) found channel %llx recording_id %d\n", __LINE__, channel_id, inst->GetRecordingId()); printf("CRecordManager::exec(ExitAll line %d) found channel %llx recording_id %d\n", __LINE__, channel_id, inst->GetRecordingId());
g_Timerd->stopTimerEvent(inst->GetRecordingId()); g_Timerd->stopTimerEvent(inst->GetRecordingId());
i++; i++;
@@ -1211,34 +1214,44 @@ int CRecordManager::exec(CMenuTarget* parent, const std::string & actionKey )
mutex.unlock(); mutex.unlock();
} }
return menu_return::RETURN_EXIT_ALL; return menu_return::RETURN_EXIT_ALL;
}else if(actionKey == "Record") } else if(actionKey == "Record")
{ {
printf("[neutrino] direct record\n"); printf("[neutrino] direct record\n");
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); 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); CRecordManager::getInstance()->Record(live_channel_id);
if(!g_InfoViewer->is_visible) // show Infoviewer if(!g_InfoViewer->is_visible) // show Infoviewer
CNeutrinoApp::getInstance()->showInfo(); CNeutrinoApp::getInstance()->showInfo();
return menu_return::RETURN_EXIT_ALL; return menu_return::RETURN_EXIT_ALL;
} }
#if 0
else else
DisplayInfoMessage(g_Locale->getText(LOCALE_RECORDING_IS_RUNNING)); DisplayInfoMessage(g_Locale->getText(LOCALE_RECORDING_IS_RUNNING));
}else if(actionKey == "Timeshift") #endif
} else if(actionKey == "Timeshift")
{ {
StartTimeshift(); StartTimeshift();
return menu_return::RETURN_EXIT_ALL; return menu_return::RETURN_EXIT_ALL;
}else if(actionKey == "Stop_record") } else if(actionKey == "Stop_record")
{ {
if(!CRecordManager::getInstance()->RecordingStatus()) { if(!CRecordManager::getInstance()->RecordingStatus()) {
ShowHintUTF(LOCALE_MAINMENU_RECORDING_STOP, g_Locale->getText(LOCALE_RECORDINGMENU_RECORD_IS_NOT_RUNNING), 450, 2); ShowHintUTF(LOCALE_MAINMENU_RECORDING_STOP, g_Locale->getText(LOCALE_RECORDINGMENU_RECORD_IS_NOT_RUNNING), 450, 2);
return menu_return::RETURN_EXIT_ALL; return menu_return::RETURN_EXIT_ALL;
} }
} }
ShowMenu(); ShowMenu();
return menu_return::RETURN_REPAINT; return menu_return::RETURN_REPAINT;
@@ -1262,23 +1275,23 @@ bool CRecordManager::ShowMenu(void)
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
bool status_ts = IsTimeshift(live_channel_id); bool status_ts = IsTimeshift(live_channel_id);
bool status_rec = RecordingStatus(live_channel_id) && !status_ts; bool status_rec = RecordingStatus(live_channel_id) && !status_ts;
//record item //record item
iteml = new CMenuForwarder(LOCALE_RECORDINGMENU_MULTIMENU_REC_AKT, (!status_rec && !status_ts), NULL, iteml = new CMenuForwarder(LOCALE_RECORDINGMENU_MULTIMENU_REC_AKT, (!status_rec && !status_ts), NULL,
this, "Record", CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED); this, "Record", CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED);
//if no recordings are running, set the focus to the record menu item //if no recordings are running, set the focus to the record menu item
menu.addItem(iteml, rec_count == 0 ? true: false); menu.addItem(iteml, rec_count == 0 ? true: false);
//timeshift item //timeshift item
iteml = new CMenuForwarder(LOCALE_RECORDINGMENU_MULTIMENU_TIMESHIFT, !status_ts, NULL, iteml = new CMenuForwarder(LOCALE_RECORDINGMENU_MULTIMENU_TIMESHIFT, !status_ts, NULL,
this, "Timeshift", CRCInput::RC_yellow, NEUTRINO_ICON_BUTTON_YELLOW); this, "Timeshift", CRCInput::RC_yellow, NEUTRINO_ICON_BUTTON_YELLOW);
menu.addItem(iteml, false); menu.addItem(iteml, false);
if(rec_count > 0) if(rec_count > 0)
{ {
menu.addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_MAINMENU_RECORDING_STOP)); menu.addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_MAINMENU_RECORDING_STOP));
mutex.lock(); mutex.lock();
int i = 0 , shortcut = 1; int i = 0 , shortcut = 1;
for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++) { 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;
@@ -1286,10 +1299,10 @@ bool CRecordManager::ShowMenu(void)
channel_ids[i] = channel_id; channel_ids[i] = channel_id;
recording_ids[i] = inst->GetRecordingId(); recording_ids[i] = inst->GetRecordingId();
std::string title; std::string title;
inst->GetRecordString(title); inst->GetRecordString(title);
const char* mode_icon = NULL; const char* mode_icon = NULL;
if (inst->tshift_mode) if (inst->tshift_mode)
mode_icon = NEUTRINO_ICON_AUTO_SHIFT; mode_icon = NEUTRINO_ICON_AUTO_SHIFT;
@@ -1301,10 +1314,10 @@ bool CRecordManager::ShowMenu(void)
if (rec_count == 1){ if (rec_count == 1){
rc_key = CRCInput::RC_stop; rc_key = CRCInput::RC_stop;
btn_icon = NEUTRINO_ICON_BUTTON_STOP; btn_icon = NEUTRINO_ICON_BUTTON_STOP;
} }
item = new CMenuForwarderNonLocalized(title.c_str(), true, NULL, selector, cnt, rc_key, NULL, mode_icon); item = new CMenuForwarderNonLocalized(title.c_str(), true, NULL, selector, cnt, rc_key, NULL, mode_icon);
item->setItemButton(btn_icon, true); item->setItemButton(btn_icon, true);
//if only one recording is running, set the focus to this menu item //if only one recording is running, set the focus to this menu item
menu.addItem(item, rec_count == 1 ? true: false); menu.addItem(item, rec_count == 1 ? true: false);
i++; i++;
@@ -1314,10 +1327,10 @@ bool CRecordManager::ShowMenu(void)
if(i > 1) //menu item "stopp all records" if(i > 1) //menu item "stopp all records"
{ {
menu.addItem(GenericMenuSeparatorLine); menu.addItem(GenericMenuSeparatorLine);
iteml = new CMenuForwarder(LOCALE_RECORDINGMENU_MULTIMENU_STOP_ALL, true, NULL, iteml = new CMenuForwarder(LOCALE_RECORDINGMENU_MULTIMENU_STOP_ALL, true, NULL,
this, "StopAll", CRCInput::RC_stop); this, "StopAll", CRCInput::RC_stop);
iteml->setItemButton(NEUTRINO_ICON_BUTTON_STOP, true); iteml->setItemButton(NEUTRINO_ICON_BUTTON_STOP, true);
//if more than one recording is running, set the focus to menu item 'stopp all records' //if more than one recording is running, set the focus to menu item 'stopp all records'
menu.addItem(iteml, rec_count > 1 ? true: false); menu.addItem(iteml, rec_count > 1 ? true: false);
} }
@@ -1330,7 +1343,8 @@ bool CRecordManager::ShowMenu(void)
if (select >= 0 && select < RECORD_MAX_COUNT) { if (select >= 0 && select < RECORD_MAX_COUNT) {
/* in theory, timer event can expire while we in menu ? lock and check again */ /* in theory, timer event can expire while we in menu ? lock and check again */
mutex.lock(); 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()) { 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]); printf("%s: channel %llx event id %d not found\n", __FUNCTION__, channel_ids[select], recording_ids[select]);
mutex.unlock(); mutex.unlock();
@@ -1338,18 +1352,23 @@ bool CRecordManager::ShowMenu(void)
} }
mutex.unlock(); mutex.unlock();
//return Stop(channel_ids[select]); //return Stop(channel_ids[select]);
return AskToStop(channel_ids[select]); return AskToStop(channel_ids[select], recording_ids[select]);
} }
return false; 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; int recording_id = 0;
std::string title; std::string title;
CRecordInstance * inst;
mutex.lock(); mutex.lock();
CRecordInstance * inst = FindInstance(channel_id); if (recid)
inst = FindInstanceID(recid);
else
inst = FindInstance(channel_id);
if(inst) { if(inst) {
recording_id = inst->GetRecordingId(); recording_id = inst->GetRecordingId();
inst->GetRecordString(title); inst->GetRecordString(title);
@@ -1551,7 +1570,7 @@ bool CRecordManager::ChooseRecDir(std::string &dir)
dir = g_settings.network_nfs_local_dir[userDecision]; dir = g_settings.network_nfs_local_dir[userDecision];
doRecord = MountDirectory(dir.c_str()); doRecord = MountDirectory(dir.c_str());
} }
} else } else
printf("%s: no network devices available\n", __FUNCTION__); printf("%s: no network devices available\n", __FUNCTION__);
} }
return doRecord; return doRecord;

View File

@@ -4,12 +4,11 @@
Copyright (C) 2001 Steffen Hehn 'McClean' Copyright (C) 2001 Steffen Hehn 'McClean'
Copyright (C) 2011 CoolStream International Ltd Copyright (C) 2011 CoolStream International Ltd
License: GPL License: GPLv2
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation;
(at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -105,7 +104,7 @@ class CRecordInstance
void FillMovieInfo(CZapitChannel * channel, APIDList & apid_lis); void FillMovieInfo(CZapitChannel * channel, APIDList & apid_lis);
record_error_msg_t MakeFileName(CZapitChannel * channel); record_error_msg_t MakeFileName(CZapitChannel * channel);
bool SaveXml(); 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); void WaitRecMsg(time_t StartTime, time_t WaitTime);
public: public:
CRecordInstance(const CTimerd::RecordingInfo * const eventinfo, std::string &dir, bool timeshift = false, bool stream_vtxt_pid = false, bool stream_pmt_pid = false); 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; }; void SetRecordingId(int id) { recording_id = id; };
int GetRecordingId(void) { return recording_id; }; int GetRecordingId(void) { return recording_id; };
t_channel_id GetChannelId(void) { return channel_id; };
std::string GetEpgTitle(void) { return epgTitle; }; std::string GetEpgTitle(void) { return epgTitle; };
MI_MOVIE_INFO * GetMovieInfo(void) { return recMovieInfo; }; MI_MOVIE_INFO * GetMovieInfo(void) { return recMovieInfo; };
void GetRecordString(std::string& str); void GetRecordString(std::string& str);
@@ -128,7 +128,8 @@ class CRecordInstance
CFrontend * frontend; 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 recmap_t::iterator recmap_iterator_t;
typedef std::list<CTimerd::RecordingInfo *> nextmap_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); bool CheckRecording(const CTimerd::RecordingInfo * const eventinfo);
void StartNextRecording(); void StartNextRecording();
void StopPostProcess(); void StopPostProcess();
void StopInstance(CRecordInstance * inst, bool remove_event = true);
CRecordInstance * FindInstance(t_channel_id); CRecordInstance * FindInstance(t_channel_id);
CRecordInstance * FindInstanceID(int recid);
void SetTimeshiftMode(CRecordInstance * inst=NULL, int mode=TSHIFT_MODE_OFF); void SetTimeshiftMode(CRecordInstance * inst=NULL, int mode=TSHIFT_MODE_OFF);
public: public:
@@ -181,7 +184,7 @@ class CRecordManager : public CMenuTarget, public CChangeObserver
bool Stop(const CTimerd::RecordingStopInfo * recinfo); bool Stop(const CTimerd::RecordingStopInfo * recinfo);
bool Update(const t_channel_id channel_id); bool Update(const t_channel_id channel_id);
bool ShowMenu(void); 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); int exec(CMenuTarget* parent, const std::string & actionKey);
bool StartAutoRecord(); bool StartAutoRecord();
bool StopAutoRecord(); bool StopAutoRecord();