//------------------------------------------------------------------------- bool CVCRControl::CVCRDevice::Record(const t_channel_id channel_id, int mode, const event_id_t epgid, const std::string& /*epgTitle*/, unsigned char apids, const time_t /*epg_time*/) { printf("Record channel_id: " PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS " epg: %llx, apids 0x%X mode \n", channel_id, epgid, apids); // leave menu (if in any) g_RCInput->postMsg( CRCInput::RC_timeout, 0 ); last_mode = CNeutrinoApp::getInstance()->getMode(); if(mode != last_mode) { CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::CHANGEMODE , mode | NeutrinoMessages::norezap ); } if(channel_id != 0) // wenn ein channel angegeben ist { if(g_Zapit->getCurrentServiceID() != channel_id) // und momentan noch nicht getuned ist { g_Zapit->zapTo_serviceID(channel_id); // dann umschalten } } if(! (apids & TIMERD_APIDS_STD)) // nicht std apid { APIDList apid_list; getAPIDs(apids,apid_list); if(!apid_list.empty()) { if(!apid_list.begin()->ac3) g_Zapit->setAudioChannel(apid_list.begin()->index); else g_Zapit->setAudioChannel(0); //sonst apid 0, also auf jeden fall ac3 aus ! } else g_Zapit->setAudioChannel(0); //sonst apid 0, also auf jeden fall ac3 aus ! } else g_Zapit->setAudioChannel(0); //sonst apid 0, also auf jeden fall ac3 aus ! if(SwitchToScart) { // Auf Scart schalten CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::VCR_ON, 0 ); // Das ganze nochmal in die queue, da obiges RC_timeout erst in der naechsten ev. loop ausgef�hrt wird // und dann das menu widget das display falsch r�cksetzt g_RCInput->postMsg( NeutrinoMessages::VCR_ON, 0 ); } deviceState = CMD_VCR_RECORD; #ifdef ENABLE_LIRC // Send IR CIRSend irs("record"); return irs.Send(); #else return true; #endif }
bool CVCRControl::CFileDevice::Record(const t_channel_id channel_id, int mode, const event_id_t epgid, const std::string& epgTitle, unsigned char apids, const time_t epg_time) { printf("Record channel_id: " PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS " epg: %llx, apids 0x%X mode %d\n", channel_id, epgid, apids, mode); CutBackNeutrino(channel_id, mode); #define MAXPIDS 64 unsigned short pids[MAXPIDS]; unsigned int numpids; unsigned int pos; CZapitClient::CCurrentServiceInfo si = g_Zapit->getCurrentServiceInfo(); numpids = 0; if (si.vpid != 0) transfer_pids(si.vpid, si.vtype ? EN_TYPE_AVC : EN_TYPE_VIDEO, 0); APIDList apid_list; getAPIDs(apids,apid_list); for(APIDList::iterator it = apid_list.begin(); it != apid_list.end(); it++) { pids[numpids++] = it->apid; transfer_pids(it->apid, EN_TYPE_AUDIO, it->ac3 ? 1 : 0); } #if 0 // FIXME : why this needed ? if(!apid_list.empty()) g_Zapit->setAudioChannel(apid_list.begin()->index); #endif CZapitClient::responseGetPIDs allpids; g_Zapit->getPIDS(allpids); if ((StreamVTxtPid) && (si.vtxtpid != 0)) { pids[numpids++] = si.vtxtpid; } if ((StreamPmtPid) && (si.pmtpid != 0)) { pids[numpids++] = si.pmtpid; } char filename[512]; // UTF-8 // Create filename for recording pos = Directory.size(); strcpy(filename, Directory.c_str()); if ((pos == 0) || (filename[pos - 1] != '/')) { filename[pos] = '/'; pos++; filename[pos] = '\0'; } pos = strlen(filename); #if 0 time_t t = time(NULL); strftime(&(filename[pos]), sizeof(filename) - pos - 1, "%Y%m%d_%H%M%S", localtime(&t)); strcat(filename, "_"); pos = strlen(filename); #endif ext_channel_name = g_Zapit->getChannelName(channel_id); if (!(ext_channel_name.empty())) { strcpy(&(filename[pos]), UTF8_TO_FILESYSTEM_ENCODING(ext_channel_name.c_str())); char * p_act = &(filename[pos]); do { p_act += strcspn(p_act, "/ \"%&-\t`'´!,:;"); if (*p_act) { *p_act++ = '_'; } } while (*p_act); if (!autoshift && g_settings.recording_save_in_channeldir) { struct stat statInfo; int res = stat(filename,&statInfo); if (res == -1) { if (errno == ENOENT) { //res = mkdir(filename,0755); res = safe_mkdir(filename); if (res == 0) { strcat(filename,"/"); } else { perror("[vcrcontrol] mkdir"); } } else { perror("[vcrcontrol] stat"); } } else { // directory exists strcat(filename,"/"); } } else strcat(filename, "_"); } pos = strlen(filename); if (g_settings.recording_epg_for_filename) { if(epgid != 0) { CShortEPGData epgdata; //if (g_Sectionsd->getEPGidShort(epgid, &epgdata)) if(sectionsd_getEPGidShort(epgid, &epgdata)) { if (!(epgdata.title.empty())) { strcpy(&(filename[pos]), epgdata.title.c_str()); char * p_act = &(filename[pos]); do { p_act += strcspn(p_act, "/ \"%&-\t`'~<>!,:;?^°$\\=*#@¤|"); if (*p_act) { *p_act++ = '_'; } } while (*p_act); } } } else if (!epgTitle.empty()) { strcpy(&(filename[pos]), epgTitle.c_str()); char * p_act = &(filename[pos]); do { p_act += strcspn(p_act, "/ \"%&-\t`'~<>!,:;?^°$\\=*#@¤|"); if (*p_act) { *p_act++ = '_'; } } while (*p_act); } } #if 1 pos = strlen(filename); time_t t = time(NULL); strftime(&(filename[pos]), sizeof(filename) - pos - 1, "%Y%m%d_%H%M%S", localtime(&t)); //pos = strlen(filename); #endif start_time = time(0); stream2file_error_msg_t error_msg = ::start_recording(filename, getMovieInfoString(CMD_VCR_RECORD, channel_id, epgid, epgTitle, apid_list, epg_time).c_str(), si.vpid, pids, numpids); if (error_msg == STREAM2FILE_OK) { deviceState = CMD_VCR_RECORD; return true; } else { RestoreNeutrino(); printf("[vcrcontrol] stream2file error code: %d\n", error_msg); #warning FIXME: Use better error message DisplayErrorMessage(g_Locale->getText( error_msg == STREAM2FILE_BUSY ? LOCALE_STREAMING_BUSY : error_msg == STREAM2FILE_INVALID_DIRECTORY ? LOCALE_STREAMING_DIR_NOT_WRITABLE : LOCALE_STREAMINGSERVER_NOCONNECT )); // UTF-8 return false; } }
std::string CVCRControl::CFileAndServerDevice::getCommandString(const CVCRCommand command, const t_channel_id channel_id, const event_id_t epgid, const std::string& epgTitle, unsigned char apids) { char tmp[40]; std::string apids_selected; const char * extCommand; std::string info1, info2; std::string extMessage = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<neutrino commandversion=\"1\">\n\t<record command=\""; switch(command) { case CMD_VCR_RECORD: extCommand = "record"; break; case CMD_VCR_STOP: extCommand = "stop"; break; case CMD_VCR_PAUSE: extCommand = "pause"; break; case CMD_VCR_RESUME: extCommand = "resume"; break; case CMD_VCR_AVAILABLE: extCommand = "available"; break; case CMD_VCR_UNKNOWN: default: extCommand = "unknown"; printf("[CVCRControl] Unknown Command\n"); } extMessage += extCommand; extMessage += "\">\n" "\t\t<channelname>"; CZapitClient::responseGetPIDs pids; g_Zapit->getPIDS (pids); CZapitClient::CCurrentServiceInfo si = g_Zapit->getCurrentServiceInfo (); APIDList apid_list; getAPIDs(apids,apid_list); apids_selected=""; for(APIDList::iterator it = apid_list.begin(); it != apid_list.end(); it++) { if(it != apid_list.begin()) apids_selected += " "; sprintf(tmp, "%u", it->apid); apids_selected += tmp; } std::string tmpstring = g_Zapit->getChannelName(channel_id); if (tmpstring.empty()) extMessage += "unknown"; else extMessage += ZapitTools::UTF8_to_UTF8XML(tmpstring.c_str()); extMessage += "</channelname>\n\t\t<epgtitle>"; tmpstring = "not available"; if (epgid != 0) { CShortEPGData epgdata; //if (g_Sectionsd->getEPGidShort(epgid, &epgdata)) { if(sectionsd_getEPGidShort(epgid, &epgdata)) { //#warning fixme sectionsd should deliver data in UTF-8 format tmpstring = epgdata.title; info1 = epgdata.info1; info2 = epgdata.info2; } } else if (!epgTitle.empty()) { tmpstring = epgTitle; } extMessage += ZapitTools::UTF8_to_UTF8XML(tmpstring.c_str()); extMessage += "</epgtitle>\n\t\t<id>"; sprintf(tmp, PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS, channel_id); extMessage += tmp; extMessage += "</id>\n\t\t<info1>"; extMessage += ZapitTools::UTF8_to_UTF8XML(info1.c_str()); extMessage += "</info1>\n\t\t<info2>"; extMessage += ZapitTools::UTF8_to_UTF8XML(info2.c_str()); extMessage += "</info2>\n\t\t<epgid>"; sprintf(tmp, "%llu", epgid); extMessage += tmp; extMessage += "</epgid>\n\t\t<mode>"; sprintf(tmp, "%d", g_Zapit->getMode()); extMessage += tmp; extMessage += "</mode>\n\t\t<videopid>"; sprintf(tmp, "%u", si.vpid); extMessage += tmp; extMessage += "</videopid>\n\t\t<audiopids selected=\""; extMessage += apids_selected; extMessage += "\">\n"; // super hack :-), der einfachste weg an die apid descriptions ranzukommen g_RemoteControl->current_PIDs = pids; g_RemoteControl->processAPIDnames(); for(unsigned int i= 0; i< pids.APIDs.size(); i++) { extMessage += "\t\t\t<audio pid=\""; sprintf(tmp, "%u", pids.APIDs[i].pid); extMessage += tmp; extMessage += "\" name=\""; extMessage += ZapitTools::UTF8_to_UTF8XML(g_RemoteControl->current_PIDs.APIDs[i].desc); extMessage += "\"/>\n"; } extMessage += "\t\t</audiopids>\n" "\t\t<vtxtpid>"; sprintf(tmp, "%u", si.vtxtpid); extMessage += tmp; extMessage += "</vtxtpid>\n" "\t</record>\n" "</neutrino>\n"; return extMessage; }
bool CVCRControl::CFileDevice::Record(const t_channel_id channel_id, int mode, const event_id_t epgid, const std::string &epgTitle, unsigned char apids,const time_t epg_time) { printf("Record channel_id: " PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS " epg: %llx, apids 0x%X mode %d\n", channel_id, epgid, apids, mode); CutBackNeutrino(channel_id, mode); int repeatcount=0; #ifndef HAVE_DREAMBOX_HARDWARE int actmode=g_Zapit->PlaybackState(); // get actual decoder mode bool sptsmode=g_settings.misc_spts; // take default from settings // aviaEXT is loaded, actual mode is not SPTS and switchoption is set , only in tvmode if ((actmode == 0) && g_settings.recording_in_spts_mode && mode == 1) { g_Zapit->PlaybackSPTS(); while ((repeatcount++ < 10) && (g_Zapit->PlaybackState() != 1)) { sleep(1); } sptsmode = true; } else if(mode==2) { if(actmode== 1) { g_Zapit->PlaybackPES(); while ((repeatcount++ < 10) && (g_Zapit->PlaybackState() != 0)) { sleep(1); } } sptsmode = false; } if (actmode == 1 && g_settings.recording_in_spts_mode && !sptsmode && mode == 1) { sptsmode = true; } #else bool sptsmode = g_settings.recording_in_spts_mode; #endif #define MAXPIDS 64 unsigned short pids[MAXPIDS]; unsigned int numpids; unsigned int pos; CZapitClient::CCurrentServiceInfo si = g_Zapit->getCurrentServiceInfo(); if (si.vpid != 0) { pids[0] = si.vpid; numpids = 1; if(sptsmode) transfer_pids(si.vpid,0x00,0); } else { /* no video pid */ numpids = 0; } APIDList apid_list; getAPIDs(apids,apid_list); for(APIDList::iterator it = apid_list.begin(); it != apid_list.end(); it++) { pids[numpids++] = it->apid; if(sptsmode) transfer_pids(it->apid,0x01, it->ac3 ? 1 : 0); } if(!apid_list.empty()) g_Zapit->setAudioChannel(apid_list.begin()->index); CZapitClient::responseGetPIDs allpids; g_Zapit->getPIDS(allpids); if ((StreamVTxtPid) && (si.vtxtpid != 0)) { pids[numpids++] = si.vtxtpid; } if ((StreamSubtitlePid) && (allpids.SubPIDs.size() > 0)) { // Add ttx-pid only once unsigned txtdone = 0; if (StreamVTxtPid) { txtdone = si.vtxtpid; } for (unsigned ii = 0 ; ii < allpids.SubPIDs.size() ; ++ii) { if (allpids.SubPIDs[ii].pid != txtdone) { pids[numpids++] = allpids.SubPIDs[ii].pid; } if (allpids.SubPIDs[ii].pid == si.vtxtpid) { txtdone = si.vtxtpid; } } } char filename[512]; // UTF-8 // Create filename for recording pos = Directory.size(); strcpy(filename, Directory.c_str()); if ((pos == 0) || (filename[pos - 1] != '/')) { filename[pos] = '/'; pos++; filename[pos] = '\0'; } time_t t = time(NULL); // %C == channel, %T == title, %I == info1, %d == date, %t == time if (FilenameTemplate.empty()) { if (g_settings.recording_epg_for_filename) FilenameTemplate = "%C_%T_"; FilenameTemplate += "%d_%t"; } std::string expandedTemplate; if (CreateTemplateDirectories) { expandedTemplate = FilenameTemplate; } else { expandedTemplate = std::string(basename(FilenameTemplate.c_str())); } unsigned int searchPos = std::string::npos; unsigned int startAt = 0; unsigned int dataLength = 0; char buf[256]; buf[255] = '\0'; if (g_settings.recording_epg_for_filename) { appendChannelName(buf,255,channel_id); dataLength = strlen(buf); while ((searchPos = expandedTemplate.find("%C",startAt)) != std::string::npos) { expandedTemplate.erase(searchPos,2); expandedTemplate.insert(searchPos,buf); startAt = searchPos + dataLength; } startAt = 0; appendEPGTitle(buf, 255, epgid, epgTitle); dataLength = strlen(buf); while ((searchPos = expandedTemplate.find("%T",startAt)) != std::string::npos) { expandedTemplate.erase(searchPos,2); expandedTemplate.insert(searchPos,buf); startAt = searchPos + dataLength; } startAt = 0; appendEPGInfo(buf, 255, epgid); dataLength = strlen(buf); while ((searchPos = expandedTemplate.find("%I",startAt)) != std::string::npos) { expandedTemplate.erase(searchPos,2); expandedTemplate.insert(searchPos,buf); startAt = searchPos + dataLength; } } strftime(buf,11,"%Y-%m-%d",localtime(&t)); dataLength = strlen(buf); startAt = 0; while ((searchPos = expandedTemplate.find("%d",startAt)) != std::string::npos) { expandedTemplate.erase(searchPos,2); expandedTemplate.insert(searchPos,buf); startAt = searchPos + dataLength; } strftime(buf,7,"%H%M%S",localtime(&t)); dataLength = strlen(buf); startAt = 0; while ((searchPos = expandedTemplate.find("%t",startAt)) != std::string::npos) { expandedTemplate.erase(searchPos,2); expandedTemplate.insert(searchPos,buf); startAt = searchPos + dataLength; } //printf("[CFileDevice] filename: %s, expandedTemplate: %s\n",filename,expandedTemplate.c_str()); strncpy(&(filename[pos]),expandedTemplate.c_str(),511-pos); stream2file_error_msg_t error_msg; if (CreateTemplateDirectories && !createRecordingDir(filename)) { error_msg = STREAM2FILE_INVALID_DIRECTORY; } else { error_msg = ::start_recording(filename, getMovieInfoString(channel_id, epgid, epg_time).c_str(), Use_O_Sync, Use_Fdatasync, ((unsigned long long)SplitSize) * 1048576ULL, numpids, pids, sptsmode, RingBuffers); } CreateTemplateDirectories = true; if (error_msg == STREAM2FILE_OK) { deviceState = CMD_VCR_RECORD; return true; } else { RestoreNeutrino(); printf("[CFileDevice] stream2file error code: %d\n", error_msg); #warning FIXME: Use better error message DisplayErrorMessage(g_Locale->getText( error_msg == STREAM2FILE_BUSY ? LOCALE_STREAMING_BUSY : error_msg == STREAM2FILE_INVALID_DIRECTORY ? LOCALE_STREAMING_DIR_NOT_WRITABLE : error_msg == STREAM2FILE_RECORDING_THREADS_FAILED ? LOCALE_STREAMING_OUT_OF_MEMORY : LOCALE_STREAMINGSERVER_NOCONNECT )); // UTF-8 return false; } }
std::string CVCRControl::CFileAndServerDevice::getMovieInfoString(const t_channel_id channel_id, const event_id_t epgid, const time_t epg_time, const std::string& epgTitle, unsigned char apids, const bool save_vtxt_pid, const bool save_sub_pids) { std::string extMessage; CMovieInfo cMovieInfo; MI_MOVIE_INFO movieInfo; std::string info1, info2; event_id_t epg_id = epgid; cMovieInfo.clearMovieInfo(&movieInfo); CZapitClient::responseGetPIDs pids; g_Zapit->getPIDS (pids); CZapitClient::CCurrentServiceInfo si = g_Zapit->getCurrentServiceInfo (); std::string tmpstring = g_Zapit->getChannelName(channel_id); if (tmpstring.empty()) movieInfo.epgChannel = "unknown"; else movieInfo.epgChannel = tmpstring; tmpstring = (epgTitle.empty()) ? "not available" : Latin1_to_UTF8(epgTitle); if (epg_id != 0) { //#define SHORT_EPG #ifdef SHORT_EPG CShortEPGData epgdata; if (g_Sectionsd->getEPGidShort(epg_id, &epgdata)) { #warning fixme sectionsd should deliver data in UTF-8 format tmpstring = Latin1_to_UTF8(epgdata.title); info1 = Latin1_to_UTF8(epgdata.info1); info2 = Latin1_to_UTF8(epgdata.info2); } #else CEPGData epgdata; bool has_epgdata = g_Sectionsd->getEPGid(epg_id, epg_time, &epgdata); if (!has_epgdata) { has_epgdata = g_Sectionsd->getActualEPGServiceKey(channel_id, &epgdata); if (has_epgdata && !epgTitle.empty() && epgTitle != epgdata.title) has_epgdata = false; if (has_epgdata) epg_id = epgdata.eventID; } if (has_epgdata) { #warning fixme sectionsd should deliver data in UTF-8 format tmpstring = Latin1_to_UTF8(epgdata.title); info1 = Latin1_to_UTF8(epgdata.info1); info2 = Latin1_to_UTF8(epgdata.info2); movieInfo.parentalLockAge = epgdata.fsk; if (!epgdata.contentClassification.empty()) movieInfo.genreMajor = epgdata.contentClassification[0]; movieInfo.length = epgdata.epg_times.dauer / 60; printf("fsk:%d, Genre:%d, Dauer: %d\r\n",movieInfo.parentalLockAge,movieInfo.genreMajor,movieInfo.length); } #endif } movieInfo.epgTitle = tmpstring; movieInfo.epgId = channel_id; movieInfo.epgInfo1 = info1; movieInfo.epgInfo2 = info2; movieInfo.epgEpgId = epg_id; movieInfo.epgMode = g_Zapit->getMode(); movieInfo.epgVideoPid = si.vpid; EPG_AUDIO_PIDS audio_pids; // super hack :-), der einfachste weg an die apid descriptions ranzukommen g_RemoteControl->current_EPGid = epg_id; g_RemoteControl->current_PIDs = pids; g_RemoteControl->processAPIDnames(); APIDList apid_list; getAPIDs(apids,apid_list); for(APIDList::iterator it = apid_list.begin(); it != apid_list.end(); ++it) { audio_pids.epgAudioPid = it->apid; audio_pids.epgAudioPidName = g_RemoteControl->current_PIDs.APIDs[it->index].desc; movieInfo.audioPids.push_back(audio_pids); } if (save_vtxt_pid) movieInfo.epgVTXPID = si.vtxtpid; if (save_sub_pids) { SUB_PIDS sub_pids; for (unsigned int i = 0; i < pids.SubPIDs.size(); i++) { sub_pids.subPid = pids.SubPIDs[i].pid; sub_pids.subPage = pids.SubPIDs[i].composition_page; sub_pids.subName = getISO639Description(pids.SubPIDs[i].desc); movieInfo.subPids.push_back(sub_pids); } } cMovieInfo.encodeMovieInfoXml(&extMessage,movieInfo); return extMessage; }