diff --git a/data/locale/deutsch.locale b/data/locale/deutsch.locale index e5e742691..23e947194 100644 --- a/data/locale/deutsch.locale +++ b/data/locale/deutsch.locale @@ -1060,6 +1060,7 @@ menu.hint_record_data_dvbsub Untertitel-Spur zu Aufnahme hinzufügen menu.hint_record_data_vtxt Teletext-Spur zu Aufnahme hinzufügen menu.hint_record_dir Wählen Sie das Aufnahmeverzeichnis menu.hint_record_end Wählen Sie zwischen maximaler Aufnahmezeit oder einem Aufnahmeende anhand der EPG-Daten +menu.hint_record_filename_template Vorlagemuster für den Dateiname bearbeiten menu.hint_record_slow_warn Zeige Warnung, wenn der Aufnahmepuffer zu überlaufen droht menu.hint_record_startstop_msg Schaltet die Meldung bei Aufnahmestart/ende ein oder aus. menu.hint_record_tdir Wählen Sie ein Verzeichnis für Ihre Timeshift-Aufnahmen im temporären Timeshift-Modus @@ -1699,6 +1700,9 @@ recordingmenu.end_of_recording_epg EPG aktuelles Event recordingmenu.end_of_recording_max max. Aufnahmezeit recordingmenu.end_of_recording_name Ende der Sofortaufnahme recordingmenu.file Direkt (Datei) +recordingmenu.filename_template Vorlage für Dateiname +recordingmenu.filename_template_hint Platzhalter werden durch folgende Werte ersetzt: +recordingmenu.filename_template_hint2 %C = Kanal, %T = Titel, %I = Info, %d = Datum, %t = Zeit recordingmenu.help Aufnahmegeräte:\n-----------------------\nServer:\nauf PC mit Hilfe eines Streaming-Programmes\n\n(analoger) Videorekorder:\nüber VCR-Ausgang\n\nDirekt (Datei):\nauf ein per NFS gemountetes Verzeichnis\noder eine interne Festplatte\nTS: SPTS-Mode Treiber laden(dbox2)\nPES: SPTS-Mode Treiber nicht laden(dbox2)\n\n\nMaximale Dateigröße:\n----------------------\nNFS V2: 2 GB (2048 MB)\nNFS V3: fast unendlich (0 MB)\nFAT: 2 GB (2048 MB)\nFAT32: 4 GB (4096 MB) recordingmenu.multimenu.ask_stop_all Wirklich alle %d Aufnahmen beenden? recordingmenu.multimenu.info_stop_all %d von %d Aufnahmen werden beendet. diff --git a/data/locale/english.locale b/data/locale/english.locale index c3d92d2ab..4c08276d9 100644 --- a/data/locale/english.locale +++ b/data/locale/english.locale @@ -1061,6 +1061,7 @@ menu.hint_record_data_dvbsub subtitle stream menu.hint_record_data_vtxt VideoText stream menu.hint_record_dir Select directory to store recordings menu.hint_record_end Stop direct record after maximal time or after current event end time +menu.hint_record_filename_template edit filename template menu.hint_record_slow_warn Show warning, when record buffer is close to overflow menu.hint_record_startstop_msg Turns the message when recording start/end on or off. menu.hint_record_tdir Select directory to save timeshift recordings\nin temporary timeshift mode @@ -1703,6 +1704,9 @@ recordingmenu.end_of_recording_epg EPG act. Event recordingmenu.end_of_recording_max max. Recordingtime recordingmenu.end_of_recording_name Endtime of Recording recordingmenu.file direct (file) +recordingmenu.filename_template filename template +recordingmenu.filename_template_hint wildcards will be replaced +recordingmenu.filename_template_hint2 %C = channel, %T = title, %I = info, %d = date, %t = time recordingmenu.help Recording devices:\n--------------------------\nserver:\nusing streaming software on a PC\n\n(analog) vcr:\nusing the vcr outlet\n\ndirect (file):\ndirectly into an NFS mounted directory\nor onto an internal hard drive\nTS: use spts mode(dbox2)\nPES: do not use spts mode(dbox2)\n\n\nMax. file size:\n---------------------\nNFS V2: 2 GB (2048 MB)\nNFS V3: almost unlimited (0 MB)\nFAT: 2 GB (2048 MB)\nFAT32: 4 GB (4096 MB) recordingmenu.multimenu.ask_stop_all really stop all %d recordings? recordingmenu.multimenu.info_stop_all %d of %d recordings will be stopped. diff --git a/src/driver/record.cpp b/src/driver/record.cpp index 9e6697b68..7e2896903 100644 --- a/src/driver/record.cpp +++ b/src/driver/record.cpp @@ -680,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); @@ -706,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); diff --git a/src/driver/record.h b/src/driver/record.h index 3205b5f06..365d24f89 100644 --- a/src/driver/record.h +++ b/src/driver/record.h @@ -79,6 +79,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; @@ -107,7 +108,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(); diff --git a/src/gui/record_setup.cpp b/src/gui/record_setup.cpp index 41d70ed3a..3bfe629bf 100644 --- a/src/gui/record_setup.cpp +++ b/src/gui/record_setup.cpp @@ -239,9 +239,12 @@ int CRecordSetup::showRecordSetup() recordingSettings->addItem(startstop_msg); } - //template - //CStringInput recordingSettings_filenameTemplate(LOCALE_RECORDINGMENU_FILENAME_TEMPLATE, &g_settings.recording_filename_template[0], 21, LOCALE_RECORDINGMENU_FILENAME_TEMPLATE_HINT, LOCALE_IPSETUP_HINT_2, "%/-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "); - //CMenuForwarder* mf11 = new CMenuForwarder(LOCALE_RECORDINGMENU_FILENAME_TEMPLATE, true, g_settings.recording_filename_template[0], &recordingSettings_filenameTemplate); + //filename template + CStringInputSMS* filename_template = new CStringInputSMS(LOCALE_RECORDINGMENU_FILENAME_TEMPLATE, &g_settings.recording_filename_template, 21, LOCALE_RECORDINGMENU_FILENAME_TEMPLATE_HINT, LOCALE_RECORDINGMENU_FILENAME_TEMPLATE_HINT2, "%/-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "); + CMenuForwarder* ft = new CMenuDForwarder(LOCALE_RECORDINGMENU_FILENAME_TEMPLATE, true, g_settings.recording_filename_template, filename_template, NULL, CRCInput::RC_1); + ft->setHint("", LOCALE_MENU_HINT_RECORD_FILE_TEMPLATE); + recordingSettings->addItem(ft); + recordingSettings->addItem(GenericMenuSeparatorLine); if (!g_settings.easymenu) { @@ -267,7 +270,7 @@ int CRecordSetup::showRecordSetup() //datasettings showRecordDataSetup(&recordingaDataSettings); - mf = new CMenuForwarder(LOCALE_RECORDINGMENU_DATA_PIDS, true, NULL, &recordingaDataSettings, NULL, CRCInput::RC_1); + mf = new CMenuForwarder(LOCALE_RECORDINGMENU_DATA_PIDS, true, NULL, &recordingaDataSettings, NULL, CRCInput::RC_2); mf->setHint("", LOCALE_MENU_HINT_RECORD_DATA); recordingSettings->addItem(mf); } diff --git a/src/neutrino.cpp b/src/neutrino.cpp index c0a56ba7e..800f75666 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -613,6 +613,7 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.recording_stream_vtxt_pid = configfile.getBool("recordingmenu.stream_vtxt_pid" , true); g_settings.recording_stream_subtitle_pids = configfile.getBool("recordingmenu.stream_subtitle_pids", true); g_settings.recording_stream_pmt_pid = configfile.getBool("recordingmenu.stream_pmt_pid" , false); + g_settings.recording_filename_template = configfile.getString("recordingmenu.filename_template" , "%C_%T%d_%t"); g_settings.recording_choose_direct_rec_dir = configfile.getInt32( "recording_choose_direct_rec_dir", 0 ); g_settings.recording_epg_for_filename = configfile.getBool("recording_epg_for_filename" , true); g_settings.recording_epg_for_end = configfile.getBool("recording_epg_for_end" , true); @@ -1099,6 +1100,7 @@ void CNeutrinoApp::saveSetup(const char * fname) configfile.setBool ("recordingmenu.stream_vtxt_pid" , g_settings.recording_stream_vtxt_pid ); configfile.setBool ("recordingmenu.stream_subtitle_pids" , g_settings.recording_stream_subtitle_pids ); configfile.setBool ("recordingmenu.stream_pmt_pid" , g_settings.recording_stream_pmt_pid ); + configfile.setString("recordingmenu.filename_template" , g_settings.recording_filename_template ); configfile.setInt32 ("recording_choose_direct_rec_dir" , g_settings.recording_choose_direct_rec_dir); configfile.setBool ("recording_epg_for_filename" , g_settings.recording_epg_for_filename ); configfile.setBool ("recording_epg_for_end" , g_settings.recording_epg_for_end ); diff --git a/src/system/locals.h b/src/system/locals.h index 18d2caae5..ec1448254 100644 --- a/src/system/locals.h +++ b/src/system/locals.h @@ -1088,6 +1088,7 @@ typedef enum LOCALE_MENU_HINT_RECORD_DATA_VTXT, LOCALE_MENU_HINT_RECORD_DIR, LOCALE_MENU_HINT_RECORD_END, + LOCALE_MENU_HINT_RECORD_FILE_TEMPLATE, LOCALE_MENU_HINT_RECORD_SLOW_WARN, LOCALE_MENU_HINT_RECORD_STARTSTOP_MSG, LOCALE_MENU_HINT_RECORD_TDIR, @@ -1730,6 +1731,9 @@ typedef enum LOCALE_RECORDINGMENU_END_OF_RECORDING_MAX, LOCALE_RECORDINGMENU_END_OF_RECORDING_NAME, LOCALE_RECORDINGMENU_FILE, + LOCALE_RECORDINGMENU_FILENAME_TEMPLATE, + LOCALE_RECORDINGMENU_FILENAME_TEMPLATE_HINT, + LOCALE_RECORDINGMENU_FILENAME_TEMPLATE_HINT2, LOCALE_RECORDINGMENU_HELP, LOCALE_RECORDINGMENU_MULTIMENU_ASK_STOP_ALL, LOCALE_RECORDINGMENU_MULTIMENU_INFO_STOP_ALL, diff --git a/src/system/locals_intern.h b/src/system/locals_intern.h index ca130e871..f2369d4a4 100644 --- a/src/system/locals_intern.h +++ b/src/system/locals_intern.h @@ -1088,6 +1088,7 @@ const char * locale_real_names[] = "menu.hint_record_data_vtxt", "menu.hint_record_dir", "menu.hint_record_end", + "menu.hint_record_filename_template", "menu.hint_record_slow_warn", "menu.hint_record_startstop_msg", "menu.hint_record_tdir", @@ -1730,6 +1731,9 @@ const char * locale_real_names[] = "recordingmenu.end_of_recording_max", "recordingmenu.end_of_recording_name", "recordingmenu.file", + "recordingmenu.filename_template", + "recordingmenu.filename_template_hint", + "recordingmenu.filename_template_hint2", "recordingmenu.help", "recordingmenu.multimenu.ask_stop_all", "recordingmenu.multimenu.info_stop_all", diff --git a/src/system/settings.h b/src/system/settings.h index 610d38d9e..f2d4255f0 100644 --- a/src/system/settings.h +++ b/src/system/settings.h @@ -376,6 +376,7 @@ struct SNeutrinoSettings int recording_slow_warning; int recording_startstop_msg; int shutdown_timer_record_type; + std::string recording_filename_template; int filesystem_is_utf8; // default plugin for ts-movieplayer (red button)