00001
00007
00008 #include <cstdio>
00009 #include <cstring>
00010 #include <climits>
00011
00012
00013 #include <algorithm>
00014 using std::lower_bound;
00015
00016
00017 #include <QTextCodec>
00018
00019
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
00075 m_lastReturnedSubtitle = sub;
00076 QStringList tmp = m_lastReturnedSubtitle.textLines;
00077 tmp.detach();
00078 return tmp;
00079 }
00080
00081
00082 startCode = sub.end + 1;
00083 }
00084
00085 if (nextSubPos == m_subtitles.end())
00086 {
00087
00088
00089 endCode = startCode + INT_MAX;
00090 }
00091 else
00092 {
00093 endCode = (*nextSubPos).start - 1;
00094 }
00095
00096
00097
00098
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
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;
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
00176
00177 free(loaded_subs);
00178 delete sub_data.rbuffer;
00179
00180 return true;
00181 }