00001
00007 #include <stdio.h>
00008 #include <cstring>
00009 #include <algorithm>
00010 #include <qtextcodec.h>
00011
00012 using std::lower_bound;
00013
00014 #include "textsubtitleparser.h"
00015 #include "xine_demux_sputext.h"
00016
00017 bool operator<(const text_subtitle_t& left,
00018 const text_subtitle_t& right)
00019 {
00020 return left.start < right.start;
00021 }
00022
00033 bool TextSubtitles::HasSubtitleChanged(uint64_t timecode) const
00034 {
00035 return (timecode < m_lastReturnedSubtitle.start ||
00036 timecode > m_lastReturnedSubtitle.end);
00037 }
00038
00046 QStringList TextSubtitles::GetSubtitles(uint64_t timecode) const
00047 {
00048 QStringList list;
00049 if (m_subtitles.empty())
00050 return list;
00051
00052 text_subtitle_t searchTarget(timecode, timecode);
00053
00054 TextSubtitleList::const_iterator nextSubPos =
00055 lower_bound(m_subtitles.begin(), m_subtitles.end(), searchTarget);
00056
00057 uint64_t startCode = 0, endCode = 0;
00058 if (nextSubPos != m_subtitles.begin())
00059 {
00060 TextSubtitleList::const_iterator currentSubPos = nextSubPos;
00061 currentSubPos--;
00062
00063 const text_subtitle_t &sub = *currentSubPos;
00064 if (sub.start <= timecode && sub.end >= timecode)
00065 {
00066
00067 m_lastReturnedSubtitle = sub;
00068 return QDeepCopy<QStringList>(m_lastReturnedSubtitle.textLines);
00069 }
00070
00071
00072 startCode = sub.end + 1;
00073 }
00074
00075 if (nextSubPos == m_subtitles.end())
00076 {
00077
00078
00079 endCode = startCode + INT_MAX;
00080 }
00081 else
00082 {
00083 endCode = (*nextSubPos).start - 1;
00084 }
00085
00086
00087
00088
00089 text_subtitle_t blankSub(startCode, endCode);
00090 m_lastReturnedSubtitle = blankSub;
00091
00092 return list;
00093 }
00094
00095 void TextSubtitles::AddSubtitle(const text_subtitle_t &newSub)
00096 {
00097 m_subtitles.push_back(newSub);
00098 }
00099
00100 void TextSubtitles::Clear(void)
00101 {
00102 m_subtitles.clear();
00103 }
00104
00105 bool TextSubtitleParser::LoadSubtitles(QString fileName, TextSubtitles &target)
00106 {
00107 demux_sputext_t sub_data;
00108 sub_data.file_ptr = fopen(fileName, "r");
00109
00110 if (!sub_data.file_ptr)
00111 return false;
00112
00113 subtitle_t *loaded_subs = sub_read_file(&sub_data);
00114 if (!loaded_subs)
00115 {
00116 fclose(sub_data.file_ptr);
00117 return false;
00118 }
00119
00120 target.SetFrameBasedTiming(!sub_data.uses_time);
00121
00122
00123
00124 QTextCodec *utf8Codec = QTextCodec::codecForName("utf8");
00125 bool utf8 = (bool)utf8Codec;
00126
00127
00128 for (int sub_i = 0; sub_i < sub_data.num; ++sub_i)
00129 {
00130 const subtitle_t *sub = &loaded_subs[sub_i];
00131 text_subtitle_t newsub(sub->start, sub->end);
00132
00133 if (!target.IsFrameBasedTiming())
00134 {
00135 newsub.start *= 10;
00136 newsub.end *= 10;
00137 }
00138
00139 for (int line = 0; line < sub->lines; ++line)
00140 {
00141 const char *subLine = sub->text[line];
00142 int lineLength = strlen(subLine);
00143
00144
00145
00146
00147
00148 utf8 = utf8 &&
00149 (utf8Codec->heuristicContentMatch(subLine, lineLength) >= lineLength);
00150
00151
00152
00153
00154
00155
00156 if (utf8)
00157 newsub.textLines.push_back(QString::fromUtf8(subLine));
00158 else
00159 newsub.textLines.push_back(QString::fromLatin1(subLine));
00160
00161 free(sub->text[line]);
00162 }
00163 target.AddSubtitle(newsub);
00164 }
00165
00166 free(loaded_subs);
00167 fclose(sub_data.file_ptr);
00168
00169 return true;
00170 }