/* * Copyright (C) 2003-2006 Gabest * http://www.gabest.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * * TODO: * - fill effect * - outline bkg still very slow * */ #include "stdafx.h" #include #include #include "SSF.h" #include "..\subpic\MemSubPic.h" namespace ssf { CRenderer::CRenderer(CCritSec* pLock) : ISubPicProviderImpl(pLock) { } CRenderer::~CRenderer() { } bool CRenderer::Open(CString fn, CString name) { m_fn.Empty(); m_name.Empty(); m_file.Free(); m_renderer.Free(); if(name.IsEmpty()) { CString str = fn; str.Replace('\\', '/'); name = str.Left(str.ReverseFind('.')); name = name.Mid(name.ReverseFind('/')+1); name = name.Mid(name.ReverseFind('.')+1); } try { if(Open(FileInputStream(fn), name)) { m_fn = fn; return true; } } catch(Exception& e) { TRACE(_T("%s\n"), e.ToString()); } return false; } bool CRenderer::Open(InputStream& s, CString name) { m_fn.Empty(); m_name.Empty(); m_file.Free(); m_renderer.Free(); try { m_file.Attach(new SubtitleFile()); m_file->Parse(s); m_renderer.Attach(new Renderer()); m_name = name; return true; } catch(Exception& e) { TRACE(_T("%s\n"), e.ToString()); } return false; } void CRenderer::Append(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, LPCWSTR str) { if(!m_file) return; try { m_file->Append(ssf::WCharInputStream(str), (float)rtStart / 10000000, (float)rtStop / 10000000); } catch(Exception& e) { TRACE(_T("%s\n"), e.ToString()); } } STDMETHODIMP CRenderer::NonDelegatingQueryInterface(REFIID riid, void** ppv) { CheckPointer(ppv, E_POINTER); *ppv = NULL; return QI(IPersist) QI(ISubStream) QI(ISubPicProvider) __super::NonDelegatingQueryInterface(riid, ppv); } // ISubPicProvider STDMETHODIMP_(POSITION) CRenderer::GetStartPosition(REFERENCE_TIME rt, double fps) { size_t k; return m_file && m_file->m_segments.Lookup((float)rt/10000000, k) ? (POSITION)(++k) : NULL; } STDMETHODIMP_(POSITION) CRenderer::GetNext(POSITION pos) { size_t k = (size_t)pos; return m_file && m_file->m_segments.GetSegment(k) ? (POSITION)(++k) : NULL; } STDMETHODIMP_(REFERENCE_TIME) CRenderer::GetStart(POSITION pos, double fps) { size_t k = (size_t)pos-1; const SubtitleFile::Segment* s = m_file ? m_file->m_segments.GetSegment(k) : NULL; return s ? (REFERENCE_TIME)(s->m_start*10000000) : 0; } STDMETHODIMP_(REFERENCE_TIME) CRenderer::GetStop(POSITION pos, double fps) { CheckPointer(m_file, 0); size_t k = (size_t)pos-1; const SubtitleFile::Segment* s = m_file ? m_file->m_segments.GetSegment(k) : NULL; return s ? (REFERENCE_TIME)(s->m_stop*10000000) : 0; } STDMETHODIMP_(bool) CRenderer::IsAnimated(POSITION pos) { return true; } STDMETHODIMP CRenderer::Render(SubPicDesc& spd, REFERENCE_TIME rt, double fps, RECT& bbox) { CheckPointer(m_file, E_UNEXPECTED); CheckPointer(m_renderer, E_UNEXPECTED); if(spd.type != MSP_RGB32) return E_INVALIDARG; CAutoLock csAutoLock(m_pLock); CRect bbox2; bbox2.SetRectEmpty(); CAutoPtrList subs; m_file->Lookup((float)rt/10000000, subs); m_renderer->NextSegment(subs); POSITION pos = subs.GetHeadPosition(); while(pos) { const Subtitle* s = subs.GetNext(pos); const RenderedSubtitle* rs = m_renderer->Lookup(s, CSize(spd.w, spd.h), spd.vidrect); if(rs) bbox2 |= rs->Draw(spd); } bbox = bbox2 & CRect(0, 0, spd.w, spd.h); return S_OK; } // IPersist STDMETHODIMP CRenderer::GetClassID(CLSID* pClassID) { return pClassID ? *pClassID = __uuidof(this), S_OK : E_POINTER; } // ISubStream STDMETHODIMP_(int) CRenderer::GetStreamCount() { return 1; } STDMETHODIMP CRenderer::GetStreamInfo(int iStream, WCHAR** ppName, LCID* pLCID) { if(iStream != 0) return E_INVALIDARG; if(ppName) { if(!(*ppName = (WCHAR*)CoTaskMemAlloc((m_name.GetLength()+1)*sizeof(WCHAR)))) return E_OUTOFMEMORY; wcscpy(*ppName, CStringW(m_name)); } if(pLCID) { *pLCID = 0; // TODO } return S_OK; } STDMETHODIMP_(int) CRenderer::GetStream() { return 0; } STDMETHODIMP CRenderer::SetStream(int iStream) { return iStream == 0 ? S_OK : E_FAIL; } STDMETHODIMP CRenderer::Reload() { CAutoLock csAutoLock(m_pLock); return !m_fn.IsEmpty() && Open(m_fn, m_name) ? S_OK : E_FAIL; } }