|
MythTV
0.26-pre
|
00001 // -*- Mode: c++ -*- 00007 // ANSI C 00008 #include <cstdio> 00009 #include <cstring> 00010 #include <climits> 00011 00012 // C++ 00013 #include <algorithm> 00014 using std::lower_bound; 00015 00016 // Qt 00017 #include <QTextCodec> 00018 00019 // MythTV 00020 #include "mythcorecontext.h" 00021 #include "ringbuffer.h" 00022 #include "textsubtitleparser.h" 00023 #include "xine_demux_sputext.h" 00024 00025 static bool operator<(const text_subtitle_t& left, 00026 const text_subtitle_t& right) 00027 { 00028 return left.start < right.start; 00029 } 00030 00041 bool TextSubtitles::HasSubtitleChanged(uint64_t timecode) const 00042 { 00043 return (timecode < m_lastReturnedSubtitle.start || 00044 timecode > m_lastReturnedSubtitle.end); 00045 } 00046 00054 QStringList TextSubtitles::GetSubtitles(uint64_t timecode) const 00055 { 00056 QStringList list; 00057 if (m_subtitles.empty()) 00058 return list; 00059 00060 text_subtitle_t searchTarget(timecode, timecode); 00061 00062 TextSubtitleList::const_iterator nextSubPos = 00063 lower_bound(m_subtitles.begin(), m_subtitles.end(), searchTarget); 00064 00065 uint64_t startCode = 0, endCode = 0; 00066 if (nextSubPos != m_subtitles.begin()) 00067 { 00068 TextSubtitleList::const_iterator currentSubPos = nextSubPos; 00069 --currentSubPos; 00070 00071 const text_subtitle_t &sub = *currentSubPos; 00072 if (sub.start <= timecode && sub.end >= timecode) 00073 { 00074 // found a sub to display 00075 m_lastReturnedSubtitle = sub; 00076 QStringList tmp = m_lastReturnedSubtitle.textLines; 00077 tmp.detach(); 00078 return tmp; 00079 } 00080 00081 // the subtitle time span has ended, let's display a blank sub 00082 startCode = sub.end + 1; 00083 } 00084 00085 if (nextSubPos == m_subtitles.end()) 00086 { 00087 // at the end of video, the blank subtitle should last until 00088 // forever 00089 endCode = startCode + INT_MAX; 00090 } 00091 else 00092 { 00093 endCode = (*nextSubPos).start - 1; 00094 } 00095 00096 // we are in a position in which there are no subtitles to display, 00097 // return an empty subtitle and create a dummy empty subtitle for this 00098 // time span so SubtitleChanged() functions also in this case 00099 text_subtitle_t blankSub(startCode, endCode); 00100 m_lastReturnedSubtitle = blankSub; 00101 00102 return list; 00103 } 00104 00105 void TextSubtitles::AddSubtitle(const text_subtitle_t &newSub) 00106 { 00107 m_lock.lock(); 00108 m_subtitles.push_back(newSub); 00109 m_lock.unlock(); 00110 } 00111 00112 void TextSubtitles::Clear(void) 00113 { 00114 m_lock.lock(); 00115 m_subtitles.clear(); 00116 m_lock.unlock(); 00117 } 00118 00119 bool TextSubtitleParser::LoadSubtitles(QString fileName, TextSubtitles &target) 00120 { 00121 demux_sputext_t sub_data; 00122 sub_data.rbuffer = RingBuffer::Create(fileName, 0, false); 00123 00124 if (!sub_data.rbuffer) 00125 return false; 00126 00127 sub_data.errs = 0; 00128 subtitle_t *loaded_subs = sub_read_file(&sub_data); 00129 if (!loaded_subs) 00130 { 00131 delete sub_data.rbuffer; 00132 return false; 00133 } 00134 00135 target.SetFrameBasedTiming(!sub_data.uses_time); 00136 00137 QTextCodec *textCodec = NULL; 00138 QString codec = gCoreContext->GetSetting("SubtitleCodec", ""); 00139 if (!codec.isEmpty()) 00140 textCodec = QTextCodec::codecForName(codec.toLatin1()); 00141 if (!textCodec) 00142 textCodec = QTextCodec::codecForName("utf-8"); 00143 if (!textCodec) 00144 { 00145 delete sub_data.rbuffer; 00146 return false; 00147 } 00148 00149 QTextDecoder *dec = textCodec->makeDecoder(); 00150 00151 // convert the subtitles to our own format and free the original structures 00152 for (int sub_i = 0; sub_i < sub_data.num; ++sub_i) 00153 { 00154 const subtitle_t *sub = &loaded_subs[sub_i]; 00155 text_subtitle_t newsub(sub->start, sub->end); 00156 00157 if (!target.IsFrameBasedTiming()) 00158 { 00159 newsub.start *= 10; // convert from csec to msec 00160 newsub.end *= 10; 00161 } 00162 00163 for (int line = 0; line < sub->lines; ++line) 00164 { 00165 const char *subLine = sub->text[line]; 00166 QString str = dec->toUnicode(subLine, strlen(subLine)); 00167 newsub.textLines.push_back(str); 00168 00169 free(sub->text[line]); 00170 } 00171 target.AddSubtitle(newsub); 00172 } 00173 00174 delete dec; 00175 // textCodec object is managed by Qt, do not delete... 00176 00177 free(loaded_subs); 00178 delete sub_data.rbuffer; 00179 00180 return true; 00181 }
1.7.6.1