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