bool SubtitleFile::Lookup(float at, CAutoPtrList<Subtitle>& subs) { if(!subs.IsEmpty()) {ASSERT(0); return false;} CAtlList<SegmentItem> sis; m_segments.Lookup(at, sis); POSITION pos = sis.GetHeadPosition(); while(pos) { SegmentItem& si = sis.GetNext(pos); CAutoPtr<Subtitle> s(DNew Subtitle(this)); if(s->Parse(si.pDef, si.start, si.stop, at)) { for(POSITION pos = subs.GetHeadPosition(); pos; subs.GetNext(pos)) { if(s->m_layer < subs.GetAt(pos)->m_layer) { subs.InsertBefore(pos, s); break; } } if(s) { subs.AddTail(s); } } } return !subs.IsEmpty(); }
CStdString MythProgramInfo::Title(bool subtitleEncoded) { char* title = cmyth_proginfo_title(*m_proginfo_t); CStdString retval(title); ref_release(title); if (subtitleEncoded) { CStdString subtitle = Subtitle(); if (!subtitle.empty()) retval.Format("%s - %s", retval, subtitle); } return retval; }
void Subtitles::load(const std::string& file_path) throw(m::Exception) { Time_ms time = 0; std::string text; Glib::ustring line; size_t line_num = 1; char buf[PIPE_BUF]; enum { GET_SUBTITLE, GET_TIME, GET_TEXT } state = GET_SUBTITLE; Glib::RefPtr<Glib::Regex> tag_regex = Glib::Regex::create("</{0,1}[a-zA-Z]>"); Glib::RefPtr<Glib::Regex> empty_line_regex = Glib::Regex::create("^\\s*$"); Glib::RefPtr<Glib::Regex> id_regex = Glib::Regex::create("^\\s*\\d+\\s*$"); Glib::RefPtr<Glib::Regex> time_regex = Glib::Regex::create( "^\\s*(\\d{1,2}):(\\d{1,2}):(\\d{1,2}),(\\d{1,3})\\s+-{1,2}>\\s+\\d{1,2}:\\d{1,2}:\\d{1,2},\\d{1,3}\\s*$" ); this->subtitles.clear(); // Открываем файл --> std::ifstream file; file.open(U2L(file_path).c_str(), std::ios::in); if(!file.is_open()) M_THROW(EE(errno)); file.exceptions(file.eofbit | file.failbit | file.badbit); // Открываем файл <-- while(file.good()) { // Считываем очередную строку из файла --> { size_t size = 0; try { char byte; bool work = true; while(work) { if(size + 1 >= sizeof buf) M_THROW(__("line %1 is too big", line_num)); file.get(byte); switch(byte) { case '\r': { file.get(byte); if(byte != '\n') file.unget(); } case '\n': { line = smart_convert(std::string(buf, buf + size)); // Отрезаем Byte order mark, если он присутствует // (http://en.wikipedia.org/wiki/Byte_order_mark). if(line_num == 1 && !line.empty() && line[0] == 0xFEFF) line = line.substr(1); work = false; } break; default: buf[size++] = byte; break; } } } catch(m::Exception& e) { // Чтобы деструктор не сгенерировал исключение file.exceptions(file.goodbit); throw; } catch(std::ofstream::failure& e) { // Чтобы деструктор не сгенерировал исключение file.exceptions(file.goodbit); if(file.bad()) M_THROW(EE(errno)); else { if(state == GET_SUBTITLE || GET_TEXT) line = smart_convert(std::string(buf, buf + size)); else M_THROW(__("unexpected end of file at line %1 ('%2')", line_num, line)); } } } // Считываем очередную строку из файла <-- // Парсим полученную строку --> switch(state) { case GET_SUBTITLE: { bool dont_break = false; if(!empty_line_regex->match(line)) { if(id_regex->match(line)) state = GET_TIME; // Иногда субтитры не имеют идентификатора else if(time_regex->match(line)) { state = GET_TIME; dont_break = true; } else M_THROW(__("invalid line %1 ('%2')", line_num, line)); } if(!dont_break) break; } case GET_TIME: { Glib::StringArrayHandle matches = time_regex->split(line); if(matches.size() < 5) M_THROW(__("invalid line %1 ('%2')", line_num, line)); else { Time_ms hours = boost::lexical_cast<int>(matches.data()[1]); Time_ms minutes = boost::lexical_cast<int>(matches.data()[2]); Time_ms seconds = boost::lexical_cast<int>(matches.data()[3]); Time_ms mseconds = boost::lexical_cast<int>(matches.data()[4]); if( hours < 0 || minutes < 0 || minutes > 59 || seconds < 0 || seconds > 59 || mseconds < 0 || mseconds > 999 ) M_THROW(__("invalid line %1 ('%2')", line_num, line)); Time_ms gotten_time = ( (hours * 60 + minutes) * 60 + seconds ) * 1000 + mseconds; if(gotten_time < time) { MLIB_SW(__( "Gotten smaller time offset than previous at line %1 in subtitles file '%2'.", line_num, file_path )); } else time = gotten_time; } state = GET_TEXT; } break; case GET_TEXT: { if(empty_line_regex->match(line)) { if(!text.empty()) { this->subtitles.push_back(Subtitle(time, text)); text = ""; } state = GET_SUBTITLE; } else { line = tag_regex->replace(line, 0, "", static_cast<Glib::RegexMatchFlags>(0)); if(!text.empty()) text += "\n"; text += line; } } break; default: MLIB_LE(); break; } // Парсим полученную строку <-- line_num++; } if(this->subtitles.empty()) M_THROW(_("there is no subtitles in this file")); }