1 /////////////////////////////////////////////////////////////////////////////
2 // Name: VobListBox.cpp
3 // Purpose: The list box to display information about streams in given VOB
4 // Author: Alex Thuering
5 // Created: 03.05.2009
6 // RCS-ID: $Id: VobListBox.cpp,v 1.32 2016/12/17 17:27:38 ntalex Exp $
7 // Copyright: (c) Alex Thuering
8 // Licence: GPL
9 /////////////////////////////////////////////////////////////////////////////
10
11 #include "VobListBox.h"
12 #include "Config.h"
13 #include "VideoPropDlg.h"
14 #include "AudioPropDlg.h"
15 #include "SubtitlePropDlg.h"
16 #include "TitlePropDlg.h"
17 #include <wx/filedlg.h>
18 #include <wx/progdlg.h>
19 #include <wx/arrimpl.cpp>
20 #include <wxSVG/mediadec_ffmpeg.h>
21 #include <wxVillaLib/utils.h>
22 #include <wxVillaLib/rc/video.png.h>
23 #include <wxVillaLib/rc/audio.png.h>
24 #include <wxVillaLib/rc/subtitle.png.h>
25
26 WX_DEFINE_OBJARRAY(RectList);
27 WX_DEFINE_OBJARRAY(RectListOfList);
28 WX_DEFINE_OBJARRAY(StringListOfList);
29
30 BEGIN_EVENT_TABLE(VobListBox, wxVListBox)
31 EVT_LEFT_DCLICK(VobListBox::OnDoubleClick)
32 EVT_BUTTON(wxID_ANY, VobListBox::OnButton)
33 EVT_CHOICE(wxID_ANY, VobListBox::OnFormatChange)
34 END_EVENT_TABLE()
35
36 const int ITEM_HEIGHT = 50;
37 #define ITEM_FONT wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)
38
VobListBox(wxScrolledWindow * parent,wxWindowID id,Vob * vob,PgcArray * pgcs,DVD * dvd,TitlePropDlg * titlePropDlg)39 VobListBox::VobListBox(wxScrolledWindow* parent, wxWindowID id, Vob* vob, PgcArray* pgcs, DVD* dvd,
40 TitlePropDlg* titlePropDlg): wxVListBox(parent, id) {
41 m_titlePropDlg = titlePropDlg;
42 m_vob = vob;
43 m_pgcs = pgcs;
44 m_dvd = dvd;
45 m_aspectRatio = pgcs->GetVideo().GetAspect();
46 m_videoImg = Scale(LoadFrame(m_vob->GetFilename()));
47 m_audioImg = Scale(wxBITMAP_FROM_MEMORY(audio).ConvertToImage());
48 m_subtitleImg = Scale(wxBITMAP_FROM_MEMORY(subtitle).ConvertToImage());
49 RefreshInfo();
50 int maxh = 300;
51 for (unsigned int i = 0; i < m_infoRect.size(); i++) {
52 int h = OnMeasureItem(i);
53 if (h > maxh)
54 maxh = h;
55 }
56 SetMinSize(wxSize(-1, maxh));
57 }
58
OnMeasureItem(size_t n) const59 wxCoord VobListBox::OnMeasureItem(size_t n) const {
60 if (n >= m_infoRect.size())
61 return ITEM_HEIGHT;
62 int h = m_infoRect[n][m_infoRect[n].size()-1].GetBottom();
63 return h + 4 > ITEM_HEIGHT ? h + 4 : ITEM_HEIGHT;
64 }
65
OnDrawItem(wxDC & dc,const wxRect & rect,size_t n) const66 void VobListBox::OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const {
67 // image
68 wxBitmap image = n == 0 ? m_videoImg : n > m_vob->GetAudioFilenames().size() ? m_subtitleImg : m_audioImg;
69 dc.DrawBitmap(image, rect.x + 2, rect.y + 2);
70
71 // info
72 dc.SetFont(ITEM_FONT);
73 dc.SetTextForeground((int)n == GetSelection() ? wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT)
74 : wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXTEXT));
75 dc.SetTextForeground(*wxBLACK);
76 wxArrayString& info = m_info[n];
77 RectList& infoRect = m_infoRect[n];
78 for (unsigned int i=0; i<info.GetCount(); i++) {
79 dc.DrawText(info[i], rect.x + infoRect[i].GetX(), rect.y + infoRect[i].GetY());
80 }
81 }
82
RefreshInfo()83 void VobListBox::RefreshInfo() {
84 SetItemCount(1 + m_vob->GetAudioFilenames().size() + m_vob->GetSubtitles().size());
85
86 m_info.Clear();
87 m_infoRect.Clear();
88
89 int choiceIdx = 0;
90 int buttonIdx = 0;
91 int itemY = 0;
92 unsigned int audioIdx = 0;
93 unsigned int subtitleIdx = 0;
94 for (unsigned int n = 0; n < 1 + m_vob->GetAudioFilenames().size(); n++) {
95 m_info.Add(wxArrayString());
96 m_infoRect.Add(RectList());
97
98 wxMemoryDC dc;
99 dc.SetFont(ITEM_FONT);
100 wxBitmap image = n == 0 ? m_videoImg : m_audioImg;
101 int x = image.GetWidth() + 8;
102 int y = 2;
103
104 // filename
105 y = AddInfo(n == 0 ? m_vob->GetFilenameDisplay() : m_vob->GetAudioFilenames()[n-1], n, dc, x, y);
106
107 // duration
108 if (n == 0) {
109 wxString s = _("Duration:") + wxString(wxT(" "));
110 if (m_vob->GetDuration()>0) {
111 int secs = (int) m_vob->GetDuration();
112 int mins = secs / 60;
113 secs %= 60;
114 int hours = mins / 60;
115 mins %= 60;
116 s += wxString::Format(wxT("%02d:%02d:%02d"), hours, mins, secs);
117 } else
118 s += wxT("N/A");
119 y = AddInfo(s, n, dc, x, y);
120 }
121
122 // stream info
123 int stIdx = n == 0 ? 0 : (int)m_vob->GetStreams().size() - m_vob->GetAudioFilenames().size() + n - 1;
124 int streamsCount = n == 0 ? (int)m_vob->GetStreams().size() - m_vob->GetAudioFilenames().size() : 1;
125 for (int stN = 0; stN < streamsCount; stN++) {
126 Stream* stream = m_vob->GetStreams()[stIdx + stN];
127 wxString srcFormat = stream->GetSourceFormat();
128 switch (stream->GetType()) {
129 case stVIDEO: {
130 m_videoChoiceIdx = choiceIdx;
131 y = AddInfo(_("Video:") + wxString(wxT(" ")) + srcFormat, n, dc, x, y);
132 wxRect& rect = m_infoRect[n][m_infoRect[n].size()-1];
133 int top = rect.GetTop();
134 int x = rect.GetRight() + 4;
135 bool copyEnabled = stream->IsCopyPossible();
136 AddChoiceCtrl(DVD::GetVideoFormatLabels(copyEnabled, false, false, m_dvd->IsHD()),
137 GetVideoFormatIdx(stream, stream->GetVideoFormat()),
138 x, itemY + top, choiceIdx, !m_vob->GetDoNotTranscode());
139 y += UpdateRect(rect, m_choiceList[choiceIdx-1]);
140 x += m_choiceList[choiceIdx-1]->GetSize().GetWidth() + 2;
141 // button
142 AddButton(x, itemY + top, buttonIdx, true, stIdx + stN);
143 break;
144 }
145 case stAUDIO: {
146 y = AddInfo(_("Audio:") + wxString(wxT(" ")) + srcFormat, n, dc, x, y);
147 wxRect& rect = m_infoRect[n][m_infoRect[n].size()-1];
148 int top = rect.GetTop();
149 int x = rect.GetRight() + 4;
150 AddChoiceCtrl(DVD::GetAudioFormatLabels(true, true), stream->GetAudioFormat(), x, itemY + top,
151 choiceIdx, !m_vob->GetDoNotTranscode());
152 y += UpdateRect(rect, m_choiceList[choiceIdx-1]);
153 x += m_choiceList[choiceIdx-1]->GetSize().GetWidth() + 2;
154 // langCode
155 wxString langCode = stream->GetLanguageCode();
156 if (stream->GetAudioFormat() != afNONE) {
157 if (audioIdx < m_pgcs->GetAudioLangCodes().size())
158 langCode = m_pgcs->GetAudioLangCodes()[audioIdx];
159 audioIdx++;
160 }
161 if (langCode.length() == 0) {
162 langCode = s_config.GetDefAudioLanguage();
163 }
164 int langIdx = DVD::GetAudioLanguageCodes().Index(langCode);
165 AddChoiceCtrl(DVD::GetAudioLanguageCodes(), langIdx, x, itemY + top, choiceIdx, true);
166 x += m_choiceList[choiceIdx-1]->GetSize().GetWidth() + 2;
167 // button
168 AddButton(x, itemY + top, buttonIdx, true, stIdx + stN);
169 break;
170 }
171 case stSUBTITLE: {
172 y = AddInfo(_("Subtitle:") + wxString(wxT(" ")) + srcFormat, n, dc, x, y);
173 wxRect& rect = m_infoRect[n][m_infoRect[n].size()-1];
174 int top = rect.GetTop();
175 int x = rect.GetRight() + 4;
176 AddChoiceCtrl(DVD::GetSubtitleFormatLabels(true, true), stream->GetSubtitleFormat(), rect.GetRight() + 4,
177 itemY + top, choiceIdx, !m_vob->GetDoNotTranscode());
178 y += UpdateRect(rect, m_choiceList[choiceIdx-1]);
179 x += m_choiceList[choiceIdx-1]->GetSize().GetWidth() + 2;
180 // lang code
181 wxString langCode = stream->GetLanguageCode();
182 if (stream->GetSubtitleFormat() != sfNONE) {
183 if (subtitleIdx < m_pgcs->GetSubPictures().size())
184 langCode = m_pgcs->GetSubPictures()[subtitleIdx]->GetLangCode();
185 subtitleIdx++;
186 }
187 if (langCode.length() == 0) {
188 langCode = s_config.GetDefSubtitleLanguage();
189 }
190 int langIdx = DVD::GetAudioLanguageCodes().Index(langCode);
191 AddChoiceCtrl(DVD::GetAudioLanguageCodes(), langIdx, x, itemY + top, choiceIdx, true);
192 x += m_choiceList[choiceIdx-1]->GetSize().GetWidth() + 2;
193 break;
194 }
195 default:
196 break;
197 }
198 }
199 itemY += y > ITEM_HEIGHT ? y + 1 : ITEM_HEIGHT + 1;
200
201 if (n == 0)
202 m_audioChoiceIdx = choiceIdx;
203 }
204
205 m_subtitleChoiceIdx = choiceIdx;
206 for (unsigned int si = 0; si < m_vob->GetSubtitles().size(); si++) {
207 m_info.Add(wxArrayString());
208 m_infoRect.Add(RectList());
209 int n = m_info.GetCount() - 1;
210
211 wxMemoryDC dc;
212 dc.SetFont(ITEM_FONT);
213 int x = m_subtitleImg.GetWidth() + 8;
214 int y = 2;
215
216 // filename
217 y = AddInfo(m_vob->GetSubtitles()[si]->GetFilename(), n, dc, x, y);
218 y = AddInfo(_("Subtitle:") + wxString(wxT(" ")) + m_vob->GetSubtitles()[si]->GetFilename().AfterLast(wxT('.')),
219 n, dc, x, y);
220
221 wxRect& rect = m_infoRect[n][m_infoRect[n].size()-1];
222 int top = rect.GetTop();
223 x = rect.GetRight() + 4;
224 int langIdx = DVD::GetAudioLanguageCodes().Index(subtitleIdx < m_pgcs->GetSubPictures().size()
225 ? m_pgcs->GetSubPictures()[subtitleIdx]->GetLangCode() : s_config.GetDefSubtitleLanguage());
226 subtitleIdx++;
227 AddChoiceCtrl(DVD::GetAudioLanguageCodes(), langIdx, x, itemY + top, choiceIdx, true);
228 y += UpdateRect(rect, m_choiceList[choiceIdx-1]);
229 x += m_choiceList[choiceIdx-1]->GetSize().GetWidth() + 2;
230 // button
231 AddButton(x, itemY + top, buttonIdx, true, m_vob->GetStreams().size() + si);
232
233 itemY += y > ITEM_HEIGHT ? y + 1 : ITEM_HEIGHT + 1;
234 }
235 }
236
AddInfo(const wxString & s,int n,wxDC & dc,int x,int y)237 int VobListBox::AddInfo(const wxString& s, int n, wxDC& dc, int x, int y) {
238 m_info[n].Add(s);
239 wxCoord w;
240 wxCoord h;
241 dc.GetTextExtent(s, &w, &h);
242 m_infoRect[n].Add(wxRect(x, y, w, h));
243 return y + h + 2;
244 }
245
246 /** Creates choice control and adds it to the list m_choiceList */
AddChoiceCtrl(wxArrayString formats,int selection,int x,int y,int & choiceIdx,bool enabled)247 void VobListBox::AddChoiceCtrl(wxArrayString formats, int selection, int x, int y, int& choiceIdx,
248 bool enabled) {
249 wxChoice* ctrl = NULL;
250 if (choiceIdx >= (int) m_choiceList.size() || m_choiceList[choiceIdx] == NULL) {
251 ctrl = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, formats);
252 ctrl->SetSelection(selection);
253 if (choiceIdx >= (int) m_choiceList.size())
254 m_choiceList.push_back(ctrl);
255 else
256 m_choiceList[choiceIdx] = ctrl;
257 } else
258 ctrl = m_choiceList[choiceIdx];
259 choiceIdx++;
260 //ctrl->Enable(enabled);
261 ctrl->SetPosition(wxPoint(x, y));
262 }
263
264 /** Increase y and height if height of control is greater that actual height */
UpdateRect(wxRect & rect,wxControl * ctrl)265 int VobListBox::UpdateRect(wxRect& rect, wxControl* ctrl) {
266 if (ctrl->GetSize().GetHeight() > rect.GetHeight()) {
267 int p = (ctrl->GetSize().GetHeight() - rect.GetHeight() + 1)/2;
268 rect.SetY(rect.GetY() + p);
269 rect.SetHeight(rect.GetHeight() + p);
270 return 2*p;
271 }
272 return 0;
273
274 }
275
276 /** Creates button and adds it to the list m_buttonList */
AddButton(int x,int y,int & buttonIdx,bool enabled,int streamIdx)277 void VobListBox::AddButton(int x, int y, int& buttonIdx, bool enabled, int streamIdx) {
278 wxButton* ctrl = NULL;
279 if (buttonIdx >= (int) m_buttonList.size() || m_buttonList[buttonIdx] == NULL) {
280 int h = (*m_choiceList.begin())->GetSize().GetHeight();
281 ctrl = new wxButton(this, wxID_ANY, wxT("..."), wxDefaultPosition, wxSize(h, h));
282 if (buttonIdx >= (int) m_buttonList.size()) {
283 m_buttonList.push_back(ctrl);
284 m_buttonStreamList.push_back(streamIdx);
285 } else {
286 m_buttonList[buttonIdx] = ctrl;
287 m_buttonStreamList[buttonIdx] = streamIdx;
288 }
289 } else {
290 ctrl = m_buttonList[buttonIdx];
291 m_buttonStreamList[buttonIdx] = streamIdx;
292 }
293 buttonIdx++;
294 ctrl->Enable(enabled);
295 ctrl->SetPosition(wxPoint(x, y));
296 }
297
LoadFrame(const wxString & filename) const298 wxImage VobListBox::LoadFrame(const wxString& filename) const {
299 wxImage image;
300 wxFfmpegMediaDecoder decoder;
301 if (decoder.Load(filename)) {
302 double duration = decoder.GetDuration();
303 if (duration > 0) {
304 image = decoder.GetNextFrame();
305 double dpos = duration < 6000 ? duration * 0.05 : 300;
306 decoder.SetPosition(dpos - 1.0);
307 for (int i = 0; i < 60; i++) {
308 image = decoder.GetNextFrame();
309 if (decoder.GetPosition() >= dpos)
310 break;
311 }
312 } else {
313 for (int i = 0; i < 30; i++)
314 image = decoder.GetNextFrame();
315 }
316 decoder.Close();
317 }
318 return image.Ok() ? image : wxBITMAP_FROM_MEMORY(video).ConvertToImage();
319 }
320
Scale(wxImage image)321 wxBitmap VobListBox::Scale(wxImage image) {
322 int h = ITEM_HEIGHT - 4;
323 int w = image.GetWidth()*h/image.GetHeight();
324 return wxBitmap(image.Scale(w, h));
325 }
326
RemoveItem(int index)327 void VobListBox::RemoveItem(int index) {
328 if (index > (int)m_vob->GetAudioFilenames().size()) {
329 // remove subtitle
330 int subtitleIdx = index - 1 - m_vob->GetAudioFilenames().size();
331 m_vob->GetSubtitles().RemoveAt(subtitleIdx);
332 // choice index = count of video stream + count of audio streams * 2 + count of audio subtitle streams
333 int choiceIdx = m_subtitleChoiceIdx + subtitleIdx;
334 m_choiceList[choiceIdx]->Hide();
335 m_choiceList.erase(m_choiceList.begin() + choiceIdx);
336 int buttonIdx = GetButtonIdx(m_vob->GetStreams().size() + subtitleIdx);
337 if (buttonIdx >= 0) {
338 m_buttonList[buttonIdx]->Hide();
339 m_buttonList.erase(m_buttonList.begin() + buttonIdx);
340 m_buttonStreamList.erase(m_buttonStreamList.begin() + buttonIdx);
341 }
342 } else {
343 // removed audio file
344 int audioIdx = index - 1;
345 m_vob->RemoveAudioFile(audioIdx);
346 // choice index = count of video stream + count of audio streams * 2
347 int choiceIdx = m_audioChoiceIdx + audioIdx*2;
348 m_choiceList[choiceIdx]->Hide();
349 m_choiceList[choiceIdx + 1]->Hide();
350 m_choiceList.erase(m_choiceList.begin() + choiceIdx);
351 m_choiceList.erase(m_choiceList.begin() + choiceIdx);
352 int buttonIdx = GetButtonIdx(m_vob->GetStreams().size() - m_vob->GetAudioFilenames().size() + audioIdx);
353 if (buttonIdx >= 0) {
354 m_buttonList[buttonIdx]->Hide();
355 m_buttonList.erase(m_buttonList.begin() + buttonIdx);
356 m_buttonStreamList.erase(m_buttonStreamList.begin() + buttonIdx);
357 }
358 }
359 RefreshInfo();
360 RefreshAll();
361 }
362
AddAudio(wxString filename)363 void VobListBox::AddAudio(wxString filename) {
364 m_vob->AddAudioFile(filename);
365 m_vob->SetDoNotTranscode(false);
366 // check if reencoding is needed
367 Stream* stream = m_vob->GetStreams()[m_vob->GetStreams().size() - 1];
368 if (m_vob->GetStreams().size() == 2 && stream->GetSourceAudioFormat() != m_dvd->GetAudioFormat())
369 stream->SetDestinationFormat(m_dvd->GetAudioFormat());
370 else if (stream->GetSourceAudioFormat() != afMP2 && stream->GetSourceAudioFormat() != afAC3)
371 stream->SetDestinationFormat(m_dvd->GetAudioFormat());
372 else if (stream->GetSourceSampleRate() != 48000)
373 stream->SetDestinationFormat(stream->GetSourceAudioFormat());
374 // add choice controls
375 m_choiceList.insert(m_choiceList.begin() + m_subtitleChoiceIdx, NULL);
376 m_choiceList.insert(m_choiceList.begin() + m_subtitleChoiceIdx, NULL);
377 // update list box
378 RefreshInfo();
379 RefreshAll();
380 }
381
AddSubtitle(wxString filename)382 void VobListBox::AddSubtitle(wxString filename) {
383 m_vob->AddSubtitlesFile(filename);
384 // update list box
385 RefreshInfo();
386 RefreshAll();
387 }
388
SetDoNotTranscode(bool value)389 void VobListBox::SetDoNotTranscode(bool value) {
390 m_vob->SetDoNotTranscode(value);
391 int choiceIdx = 0;
392 for (unsigned int stIdx = 0; stIdx < m_vob->GetStreams().size(); stIdx++) {
393 Stream* stream = m_vob->GetStreams()[stIdx];
394 switch (stream->GetType()) {
395 case stVIDEO:
396 if (value)
397 m_choiceList[choiceIdx]->SetSelection(vfCOPY-1); // vfNONE is not in the selection list
398 choiceIdx++;
399 break;
400 case stAUDIO:
401 if (value)
402 m_choiceList[choiceIdx]->SetSelection(afCOPY);
403 choiceIdx += 2;
404 break;
405 default:
406 break;
407 }
408 }
409 }
410
411 /**
412 * Returns true if "do not transcode active ist"
413 */
GetDoNotTranscode()414 bool VobListBox::GetDoNotTranscode() {
415 return m_vob->GetDoNotTranscode();
416 }
417
HasAudioFiles()418 bool VobListBox::HasAudioFiles() {
419 return m_vob->GetAudioFilenames().size() > 0;
420 }
421
SetValues()422 void VobListBox::SetValues() {
423 unsigned int choiceIdx = 0;
424 unsigned int audioIdx = 0;
425 unsigned int subtitleIdx = 0;
426 for (unsigned int stIdx = 0; stIdx < m_vob->GetStreams().size(); stIdx++) {
427 Stream* stream = m_vob->GetStreams()[stIdx];
428 switch (stream->GetType()) {
429 case stVIDEO: {
430 int vf = m_choiceList[choiceIdx++]->GetSelection();
431 if (m_dvd->IsHD()) {
432 if (stream->IsCopyPossible()) {
433 if (vf == 0) {
434 vf = vfCOPY;
435 } else if (vf <= 6) {
436 vf += vfPAL_HALF_HD - 1;
437 } else
438 vf -= 5;
439 } else {
440 if (vf <= 5) {
441 vf += vfPAL_HALF_HD;
442 } else
443 vf -= 4;
444 }
445 } else {
446 vf += (stream->IsCopyPossible() ? 1 : 2);
447 }
448 stream->SetDestinationFormat(vf);
449 if (stream->GetVideoFormat() != vfCOPY)
450 m_vob->SetDoNotTranscode(false);
451 break;
452 }
453 case stAUDIO:
454 stream->SetDestinationFormat(m_choiceList[choiceIdx++]->GetSelection());
455 if (stream->GetAudioFormat() != afCOPY)
456 m_vob->SetDoNotTranscode(false);
457 if (stream->GetAudioFormat() != afNONE) {
458 if (audioIdx >= m_pgcs->GetAudioLangCodes().size())
459 m_pgcs->GetAudioLangCodes().push_back(m_choiceList[choiceIdx]->GetStringSelection());
460 else
461 m_pgcs->GetAudioLangCodes()[audioIdx] = m_choiceList[choiceIdx]->GetStringSelection();
462 audioIdx++;
463 }
464 choiceIdx++;
465 break;
466 case stSUBTITLE:
467 stream->SetDestinationFormat(m_choiceList[choiceIdx++]->GetSelection());
468 if (stream->GetSubtitleFormat() != sfCOPY)
469 m_vob->SetDoNotTranscode(false);
470 if (stream->GetSubtitleFormat() != sfNONE) {
471 if (m_pgcs->GetSubPictures().size() <= subtitleIdx)
472 m_pgcs->GetSubPictures().push_back(new SubPicture(m_choiceList[choiceIdx]->GetStringSelection()));
473 else
474 m_pgcs->GetSubPictures()[subtitleIdx]->SetLangCode(m_choiceList[choiceIdx]->GetStringSelection());
475 subtitleIdx++;
476 }
477 choiceIdx++;
478 break;
479 default:
480 break;
481 }
482 }
483 for (unsigned int si = 0; si < m_vob->GetSubtitles().size(); si++) {
484 if (m_pgcs->GetSubPictures().size() <= subtitleIdx)
485 m_pgcs->GetSubPictures().push_back(new SubPicture(m_choiceList[choiceIdx++]->GetStringSelection()));
486 else
487 m_pgcs->GetSubPictures()[subtitleIdx]->SetLangCode(m_choiceList[choiceIdx++]->GetStringSelection());
488 subtitleIdx++;
489 }
490 }
491
492 /** Returns index of choice control for given stream */
GetChoiceIdx(unsigned int streamIdx)493 int VobListBox::GetChoiceIdx(unsigned int streamIdx) {
494 int choiceIdx = 0;
495 for (unsigned int stIdx = 0; stIdx < streamIdx; stIdx++) {
496 Stream* stream = m_vob->GetStreams()[stIdx];
497 switch (stream->GetType()) {
498 case stVIDEO:
499 choiceIdx++;
500 break;
501 case stAUDIO:
502 case stSUBTITLE:
503 choiceIdx += 2;
504 break;
505 default:
506 break;
507 }
508 }
509 return choiceIdx;
510 }
511
512 /** Returns index of button for given stream */
GetButtonIdx(unsigned int streamIdx)513 int VobListBox::GetButtonIdx(unsigned int streamIdx) {
514 for (unsigned int btIdx = 0; btIdx < m_buttonStreamList.size(); btIdx++) {
515 if (m_buttonStreamList[btIdx] == (int) streamIdx) {
516 return btIdx;
517 }
518 }
519 return -1;
520 }
521
522 /** Get video format */
GetVideoFormat()523 int VobListBox::GetVideoFormat() {
524 return m_choiceList[m_videoChoiceIdx]->GetSelection();
525 }
526
527 /** Gets video format index */
GetVideoFormatIdx(Stream * stream,VideoFormat videoFormat)528 int VobListBox::GetVideoFormatIdx(Stream* stream, VideoFormat videoFormat) {
529 bool copyEnabled = stream->IsCopyPossible();
530 int vf = videoFormat;
531 if (m_dvd->IsHD()) {
532 if (vf >= vfPAL_HALF_HD) {
533 vf = vf - vfPAL_HALF_HD + (copyEnabled ? 1 : 0);
534 } else
535 vf = vf >= vfPAL && vf < vfPAL_HALF_HD ? vf + (copyEnabled ? 5 : 4) : 0;
536 } else {
537 vf -= (copyEnabled ? 1 : 2);
538 }
539 return vf;
540 }
541
542 /** Sets audio format */
SetVideoFormat(int videoFormat)543 void VobListBox::SetVideoFormat(int videoFormat) {
544 m_choiceList[m_videoChoiceIdx]->SetSelection(videoFormat);
545 }
546
547 /** Get audio format */
GetAudioFormat(unsigned int streamIdx)548 int VobListBox::GetAudioFormat(unsigned int streamIdx) {
549 return m_choiceList[GetChoiceIdx(streamIdx)]->GetSelection();
550 }
551
552 /** Sets audio format */
SetAudioFormat(unsigned int streamIdx,int audioFormat)553 void VobListBox::SetAudioFormat(unsigned int streamIdx, int audioFormat) {
554 m_choiceList[GetChoiceIdx(streamIdx)]->SetSelection(audioFormat);
555 }
556
557 /** Get audio language code */
GetAudioLangCode(unsigned int streamIdx)558 wxString VobListBox::GetAudioLangCode(unsigned int streamIdx) {
559 return m_choiceList[GetChoiceIdx(streamIdx) + 1]->GetStringSelection();
560 }
561
562 /** Sets audio language code */
SetAudioLangCode(unsigned int streamIdx,wxString langCode)563 void VobListBox::SetAudioLangCode(unsigned int streamIdx, wxString langCode) {
564 m_choiceList[GetChoiceIdx(streamIdx) + 1]->SetSelection(DVD::GetAudioLanguageCodes().Index(langCode));
565 }
566
567 /**
568 * Get subtitle language code (for property dialog, ignores muxed subtitles)
569 */
GetSubtitleLangCode(int subtitleIndex)570 wxString VobListBox::GetSubtitleLangCode(int subtitleIndex) {
571 return m_choiceList[m_subtitleChoiceIdx + subtitleIndex]->GetStringSelection();
572 }
573
574 /**
575 * Sets subtitle language code (for property dialog, ignores muxed subtitles)
576 */
SetSubtitleLangCode(int subtitleIndex,wxString langCode)577 void VobListBox::SetSubtitleLangCode(int subtitleIndex, wxString langCode) {
578 m_choiceList[m_subtitleChoiceIdx + subtitleIndex]->SetSelection(DVD::GetAudioLanguageCodes().Index(langCode));
579 }
580
581 /**
582 * Shows subtitle properties dialog
583 */
ShowPropDialog()584 void VobListBox::ShowPropDialog() {
585 if (GetSelection() == 0) {
586 for (unsigned int i = 0; i < m_vob->GetStreams().size(); i++)
587 if (m_vob->GetStreams()[i]->GetType() == stVIDEO)
588 ShowPropDialog(i);
589 } else if (GetSelection() < 1 + (int) m_vob->GetAudioFilenames().GetCount()) {
590 // audio
591 int audioIdx = GetSelection() - 1;
592 int streamIdx = m_vob->GetStreams().size() - m_vob->GetAudioFilenames().GetCount() + audioIdx;
593 ShowPropDialog(streamIdx);
594 } else {
595 // subtitle
596 int idx = GetSelection() - 1 - m_vob->GetAudioFilenames().GetCount();
597 ShowPropDialog(m_vob->GetStreams().size() + idx);
598 }
599 }
600
601 /** Shows subtitle properties dialog */
ShowPropDialog(unsigned int streamIdx)602 void VobListBox::ShowPropDialog(unsigned int streamIdx) {
603 if (streamIdx >= m_vob->GetStreams().size()) {
604 // subtitle
605 unsigned int idx = streamIdx - m_vob->GetStreams().size();
606 if (idx >= m_vob->GetSubtitles().size())
607 return;
608 TextSub* textsub = m_vob->GetSubtitles()[idx];
609
610 if (!TextSub::IsFontMapInitialized()) {
611 wxProgressDialog pDlg(wxT("DVDStyler"), _("Please wait..."), 99, this,
612 wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_SMOOTH);
613 pDlg.Show();
614 pDlg.SetFocus();
615 pDlg.Pulse();
616 TextSub::GetFontMap();
617 pDlg.Hide();
618 }
619
620 SubtitlePropDlg dialog(this, textsub, GetSubtitleLangCode(idx));
621 if (dialog.ShowModal() == wxID_OK) {
622 SetSubtitleLangCode(idx, dialog.GetLangCode());
623 }
624 } else {
625 Stream* stream = m_vob->GetStreams()[streamIdx];
626 if (stream->GetType() == stVIDEO) {
627 // video
628 SetValues(); // update destination format
629 if (!m_titlePropDlg->ApplyChaptersCtrl())
630 return;
631 VideoPropDlg dialog(this, m_dvd, m_vob, m_aspectRatio);
632 if (dialog.ShowModal() == wxID_OK) {
633 SetVideoFormat(GetVideoFormatIdx(stream, dialog.GetVideoFormat()));
634 m_aspectRatio = dialog.GetAspectRatio();
635 UpdateDoNotTranscodeCheck();
636 m_titlePropDlg->UpdateChaptersCtrl();
637 }
638 } else if (stream->GetType() == stAUDIO) {
639 // audio
640 SetValues(); // update destination format
641 int audioIdx = streamIdx - (m_vob->GetStreams().size() - m_vob->GetAudioFilenames().GetCount());
642 wxString audioFile = audioIdx >= 0 ? m_vob->GetAudioFilenames()[audioIdx] : wxT("");
643 AudioPropDlg dialog(this, m_vob, audioFile, GetAudioLangCode(streamIdx), streamIdx);
644 if (dialog.ShowModal() == wxID_OK) {
645 SetAudioFormat(streamIdx, dialog.GetAudioFormat());
646 SetAudioLangCode(streamIdx, dialog.GetLangCode());
647 UpdateDoNotTranscodeCheck();
648 }
649 }
650 }
651 }
652
653 /** Processes a double click event */
OnDoubleClick(wxMouseEvent & evt)654 void VobListBox::OnDoubleClick(wxMouseEvent& evt) {
655 ShowPropDialog();
656 }
657
658 /** Processes a button event */
OnButton(wxCommandEvent & event)659 void VobListBox::OnButton(wxCommandEvent& event) {
660 int buttonIdx = 0;
661 for (vector<wxButton*>::iterator btIt = m_buttonList.begin(); btIt < m_buttonList.end(); btIt++) {
662 if (*btIt == event.GetEventObject())
663 break;
664 buttonIdx++;
665 }
666 ShowPropDialog(m_buttonStreamList[buttonIdx]);
667 }
668
UpdateDoNotTranscodeCheck()669 void VobListBox::UpdateDoNotTranscodeCheck() {
670 if (m_vob->GetDoNotTranscode()) {
671 SetValues(); // update destination format
672 if (!m_vob->GetDoNotTranscode())
673 m_titlePropDlg->UpdateDoNotTranscodeCheck();
674 }
675 }
676
677 /** Processes a format change event */
OnFormatChange(wxCommandEvent & event)678 void VobListBox::OnFormatChange(wxCommandEvent& event) {
679 UpdateDoNotTranscodeCheck();
680 }
681