1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2000-2012
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / Osmo4 wxWidgets GUI
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  *
25  */
26 
27 #include "fileprops.h"
28 #include "wxOsmo4.h"
29 #include "Playlist.h"
30 #include <wx/filename.h>
31 #include <gpac/modules/codec.h>
32 #include <gpac/modules/service.h>
33 #include <gpac/constants.h>
34 /*ISO 639 languages*/
35 #include <gpac/iso639.h>
36 
37 
wxFileProps(wxWindow * parent)38 wxFileProps::wxFileProps(wxWindow *parent)
39 	: wxDialog(parent, -1, wxString(_T("File Properties")))
40 {
41 
42 	m_pApp = (wxOsmo4Frame *)parent;
43 	SetSize(540, 260);
44 	assert(m_pApp->m_pPlayList);
45 
46 	m_pTreeView = new wxTreeCtrl(this, ID_TREE_VIEW, wxPoint(4, 2), wxSize(200, 180), wxTR_DEFAULT_STYLE | wxSUNKEN_BORDER);
47 
48 	new wxStaticText(this, 0, _T("Information"), wxPoint(210, 2), wxSize(60, 20));
49 	m_pViewSel = new wxComboBox(this, ID_VIEW_SEL, _T(""), wxPoint(280, 2), wxSize(120, 24), 0, NULL, wxCB_READONLY);
50 	m_pViewSel->Append(wxT("General"));
51 	m_pViewSel->Append(wxT("Streams"));
52 	m_pViewSel->Append(wxT("Playback"));
53 	m_pViewSel->Append(wxT("Network"));
54 	m_pViewSel->SetSelection(0);
55 
56 	m_pViewInfo = new wxTextCtrl(this, -1, wxT(""), wxPoint(210, 30), wxSize(320, 200), wxTE_MULTILINE | wxTE_READONLY | wxHSCROLL | wxSUNKEN_BORDER);
57 
58 #ifdef WIN32
59 	m_pViewInfo->SetBackgroundColour(wxColour(wxT("LIGHT GREY")));
60 #endif
61 
62 	m_pViewWI = new wxButton(this, ID_VIEW_WI, wxT("View World Info"), wxPoint(4, 174), wxSize(200, 40));
63 	m_pViewSG = new wxButton(this, ID_VIEW_SG, wxT("View Scene Graph"), wxPoint(4, 220), wxSize(200, 40));
64 
65 
66 	wxString str = m_pApp->m_pPlayList->GetDisplayName();
67 	str += wxT(" Properties");
68 	SetTitle(str);
69 
70 	m_pTimer = new wxTimer();
71 	m_pTimer->SetOwner(this, ID_OD_TIMER);
72 	m_pTimer->Start(500, 0);
73 	RewriteODTree();
74 
75 }
76 
~wxFileProps()77 wxFileProps::~wxFileProps()
78 {
79 	m_pTimer->Stop();
80 	delete m_pTimer;
81 }
82 
83 
BEGIN_EVENT_TABLE(wxFileProps,wxDialog)84 BEGIN_EVENT_TABLE(wxFileProps, wxDialog)
85 	EVT_TREE_ITEM_ACTIVATED(ID_TREE_VIEW, wxFileProps::OnSetSelection)
86 	EVT_TREE_SEL_CHANGED(ID_TREE_VIEW, wxFileProps::OnSetSelection)
87 	EVT_TREE_ITEM_EXPANDED(ID_TREE_VIEW, wxFileProps::OnSetSelection)
88 	EVT_TREE_ITEM_COLLAPSED(ID_TREE_VIEW, wxFileProps::OnSetSelection)
89 	EVT_TIMER(ID_OD_TIMER, wxFileProps::OnTimer)
90 	EVT_BUTTON(ID_VIEW_SG, wxFileProps::OnViewSG)
91 	EVT_BUTTON(ID_VIEW_WI, wxFileProps::OnViewWorld)
92 	EVT_COMBOBOX(ID_VIEW_SEL, wxFileProps::OnSelectInfo)
93 END_EVENT_TABLE()
94 
95 void wxFileProps::RewriteODTree()
96 {
97 	GF_ObjectManager *root_odm = gf_term_get_root_object(m_pApp->m_term);
98 	if (!root_odm) return;
99 
100 	m_pTreeView->DeleteAllItems();
101 	ODTreeData *root = new ODTreeData(root_odm);
102 	m_pTreeView->AddRoot(wxT("Root OD"), -1, -1, root);
103 	wxTreeItemId rootId = m_pTreeView->GetRootItem();
104 
105 	WriteInlineTree(root);
106 	SetInfo(root_odm);
107 }
108 
WriteInlineTree(ODTreeData * root)109 void wxFileProps::WriteInlineTree(ODTreeData *root)
110 {
111 	/*browse all ODs*/
112 	u32 count = gf_term_get_object_count(m_pApp->m_term, root->m_pODMan);
113 
114 	for (u32 i=0; i<count; i++) {
115 		GF_ObjectManager *odm = gf_term_get_object(m_pApp->m_term, root->m_pODMan, i);
116 		if (!odm) return;
117 		ODTreeData *odd = new ODTreeData(odm);
118 		m_pTreeView->AppendItem(root->GetId(), wxT("Object Descriptor"), -1, -1, odd);
119 
120 		/*if inline propagate*/
121 		switch (gf_term_object_subscene_type(m_pApp->m_term, odm)) {
122 		case 1:
123 			m_pTreeView->SetItemText(odd->GetId(), wxT("Root Scene"));
124 			WriteInlineTree(odd);
125 			break;
126 		case 2:
127 			m_pTreeView->SetItemText(odd->GetId(), wxT("Inline Scene"));
128 			WriteInlineTree(odd);
129 			break;
130 		case 3:
131 			m_pTreeView->SetItemText(odd->GetId(), wxT("Extern Proto Lib"));
132 			break;
133 		default:
134 			break;
135 		}
136 	}
137 }
138 
OnSetSelection(wxTreeEvent & event)139 void wxFileProps::OnSetSelection(wxTreeEvent& event)
140 {
141 	ODTreeData *odd = (ODTreeData *) m_pTreeView->GetItemData(event.GetItem());
142 	SetInfo(odd->m_pODMan);
143 }
144 
SetInfo(GF_ObjectManager * odm)145 void wxFileProps::SetInfo(GF_ObjectManager *odm)
146 {
147 	m_current_odm = odm;
148 
149 	switch (m_pViewSel->GetSelection()) {
150 	case 3:
151 		SetNetworkInfo();
152 		break;
153 	case 2:
154 		SetDecoderInfo();
155 		break;
156 	case 1:
157 		SetStreamsInfo();
158 		break;
159 	default:
160 		SetGeneralInfo();
161 		break;
162 	}
163 }
164 
OnTimer(wxTimerEvent & WXUNUSED (event))165 void wxFileProps::OnTimer(wxTimerEvent& WXUNUSED(event))
166 {
167 	switch (m_pViewSel->GetSelection()) {
168 	case 2:
169 		SetDecoderInfo();
170 		break;
171 	}
172 }
OnSelectInfo(wxCommandEvent & WXUNUSED (event))173 void wxFileProps::OnSelectInfo(wxCommandEvent & WXUNUSED(event) )
174 {
175 	SetInfo(m_current_odm);
176 }
177 
SetGeneralInfo()178 void wxFileProps::SetGeneralInfo()
179 {
180 	wxString info;
181 	GF_MediaInfo odi;
182 	u32 h, m, s;
183 	u32 i, j;
184 
185 	info = wxT("");
186 	m_pViewInfo->Clear();
187 	m_pViewInfo->AppendText(info);
188 
189 	if (!m_current_odm || gf_term_get_object_info(m_pApp->m_term, m_current_odm, &odi) != GF_OK) return;
190 
191 	if (odi.has_profiles) info += wxT("Initial ");
192 	info += wxString::Format(wxT("Object Descriptor ID %d\n"), odi.od->objectDescriptorID);
193 	if (odi.duration) {
194 		h = (u32) (odi.duration / 3600);
195 		m = (u32) (odi.duration / 60) - h*60;
196 		s = (u32) (odi.duration) - h*3600 - m*60;
197 		info += wxString::Format(wxT("Duration %02d:%02d:%02d\n"), h, m, s);
198 	} else {
199 		info += wxT("Unknown duration\n");
200 	}
201 
202 	if (odi.owns_service) {
203 		info += wxT("Service Handler: ") + wxString(odi.service_handler, wxConvUTF8) + wxT("\n");
204 		info += wxT("Service URL: ") + wxString(odi.service_url, wxConvUTF8) + wxT("\n");
205 	}
206 
207 	if (odi.od->URLString) {
208 		info += wxT("Remote OD - URL: ") + wxString(odi.od->URLString, wxConvUTF8) + wxT("\n");
209 	}
210 
211 	if (odi.codec_name) {
212 		switch (odi.od_type) {
213 		case GF_STREAM_VISUAL:
214 			info += wxString::Format(wxT("Video Object: Width %d - Height %d\n"), odi.width, odi.height);
215 			info += wxT("Media Codec ") + wxString(odi.codec_name, wxConvUTF8) + wxT("\n");
216 			break;
217 		case GF_STREAM_AUDIO:
218 			info += wxString::Format(wxT("Audio Object: Sample Rate %d - %d channels\n"), odi.sample_rate, odi.num_channels);
219 			info += wxT("Media Codec ") + wxString(odi.codec_name, wxConvUTF8) + wxT("\n");
220 			break;
221 		case GF_STREAM_PRIVATE_SCENE:
222 		case GF_STREAM_SCENE:
223 			if (odi.width && odi.height) {
224 				info += wxString::Format(wxT("Scene Description: Width %d - Height %d\n"), odi.width, odi.height);
225 			} else {
226 				info += wxT("Scene Description: No size specified\n");
227 			}
228 			info += wxT("Scene Codec ") + wxString(odi.codec_name, wxConvUTF8) + wxT("\n");
229 			break;
230 		case GF_STREAM_TEXT:
231 			if (odi.width && odi.height) {
232 				info += wxString::Format(wxT("Text Object: Width %d - Height %d\n"), odi.width, odi.height);
233 			} else {
234 				info += wxString::Format(wxT("Text Object: No size specified\n"));
235 			}
236 			info += wxT("Text Codec ") + wxString(odi.codec_name, wxConvUTF8) + wxT("\n");
237 			break;
238 		}
239 	}
240 	if (odi.protection==2) info += wxT("Encrypted Media NOT UNLOCKED");
241 	else if (odi.protection==1) info += wxT("Encrypted Media");
242 
243 	if (!gf_list_count(odi.od->OCIDescriptors)) {
244 		m_pViewInfo->Clear();
245 		m_pViewInfo->AppendText(info);
246 		return;
247 	}
248 
249 	info += wxT("\nObject Content Information:\n");
250 
251 	/*check OCI (not everything interests us) - FIXME: support for unicode*/
252 	for (i=0; i<gf_list_count(odi.od->OCIDescriptors); i++) {
253 		GF_Descriptor *desc = (GF_Descriptor *) gf_list_get(odi.od->OCIDescriptors, i);
254 		switch (desc->tag) {
255 		case GF_ODF_SEGMENT_TAG:
256 		{
257 			GF_Segment *sd = (GF_Segment *) desc;
258 			info += wxT("\nSegment Descriptor:\nName: ") + wxString((char *) sd->SegmentName, wxConvUTF8);
259 			info += wxString::Format(wxT(" - start time %g sec - duration %g sec\n"), sd->startTime, sd->Duration);
260 		}
261 		break;
262 		case GF_ODF_CC_NAME_TAG:
263 		{
264 			GF_CC_Name *ccn = (GF_CC_Name *)desc;
265 			info += wxT("\nContent Creators:\n");
266 			for (j=0; j<gf_list_count(ccn->ContentCreators); j++) {
267 				GF_ContentCreatorInfo *ci = (GF_ContentCreatorInfo *) gf_list_get(ccn->ContentCreators, j);
268 				if (!ci->isUTF8) continue;
269 				info += wxT("\t") + wxString(ci->contentCreatorName, wxConvUTF8) + wxT("\n");
270 			}
271 		}
272 		break;
273 
274 		case GF_ODF_SHORT_TEXT_TAG:
275 		{
276 			GF_ShortTextual *std = (GF_ShortTextual *)desc;
277 			info += wxT("\n") + wxString(std->eventName, wxConvUTF8) + wxT(": ") + wxString(std->eventText, wxConvUTF8) + wxT("\n");
278 		}
279 		break;
280 		/*todo*/
281 		case GF_ODF_CC_DATE_TAG:
282 			break;
283 		default:
284 			break;
285 		}
286 
287 	}
288 
289 	m_pViewInfo->Clear();
290 	m_pViewInfo->AppendText(info);
291 }
292 
SetStreamsInfo()293 void wxFileProps::SetStreamsInfo()
294 {
295 	u32 i, count;
296 	wxString info;
297 	GF_MediaInfo odi;
298 	char code[5];
299 
300 	info = wxT("");
301 	m_pViewInfo->Clear();
302 	m_pViewInfo->AppendText(info);
303 
304 	if (!m_current_odm || gf_term_get_object_info(m_pApp->m_term, m_current_odm, &odi) != GF_OK) return;
305 
306 	if (odi.has_profiles) {
307 		info += wxString::Format(wxT("\tOD Profile@Level %d\n"), odi.OD_pl);
308 		info += wxString::Format(wxT("\tScene Profile@Level %d\n"), odi.scene_pl);
309 		info += wxString::Format(wxT("\tGraphics Profile@Level %d\n"), odi.graphics_pl);
310 		info += wxString::Format(wxT("\tAudio Profile@Level %d\n"), odi.audio_pl);
311 		info += wxString::Format(wxT("\tVisual Profile@Level %d\n"), odi.scene_pl);
312 		if (odi.inline_pl) info += wxT("\tInline Content use same profiles\n");
313 		info += wxT("\n");
314 	}
315 
316 	count = gf_list_count(odi.od->ESDescriptors);
317 
318 	for (i=0; i<count; i++) {
319 		GF_ESD *esd = (GF_ESD *) gf_list_get(odi.od->ESDescriptors, i);
320 
321 		info += wxString::Format(wxT("Stream ID %d - Clock ID %d\n"), esd->ESID, esd->OCRESID);
322 		if (esd->dependsOnESID) {
323 			info += wxString::Format(wxT("\tDepends on Stream ID %d for decoding\n"), esd->dependsOnESID);
324 		}
325 		switch (esd->decoderConfig->streamType) {
326 		case GF_STREAM_OD:
327 			info += wxString::Format(wxT("\tOD Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
328 			break;
329 		case GF_STREAM_OCR:
330 			info += wxT("\tObject Clock Reference Stream\n");
331 			break;
332 		case GF_STREAM_SCENE:
333 			info += wxString::Format(wxT("\tScene Description Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
334 			break;
335 		case GF_STREAM_PRIVATE_SCENE:
336 			info += wxString::Format(wxT("\tGPAC Private Scene Description Stream\n"));
337 			break;
338 		case GF_STREAM_VISUAL:
339 			info += wxT("\tVisual Stream - media type: ");
340 			switch (esd->decoderConfig->objectTypeIndication) {
341 			case GPAC_OTI_VIDEO_MPEG4_PART2:
342 				info += wxT("MPEG-4\n");
343 				break;
344 			case GPAC_OTI_VIDEO_MPEG2_SIMPLE:
345 				info += wxT("MPEG-2 Simple Profile\n");
346 				break;
347 			case GPAC_OTI_VIDEO_MPEG2_MAIN:
348 				info += wxT("MPEG-2 Main Profile\n");
349 				break;
350 			case GPAC_OTI_VIDEO_MPEG2_SNR:
351 				info += wxT("MPEG-2 SNR Profile\n");
352 				break;
353 			case GPAC_OTI_VIDEO_MPEG2_SPATIAL:
354 				info += wxT("MPEG-2 Spatial Profile\n");
355 				break;
356 			case GPAC_OTI_VIDEO_MPEG2_HIGH:
357 				info += wxT("MPEG-2 High Profile\n");
358 				break;
359 			case GPAC_OTI_VIDEO_MPEG2_422:
360 				info += wxT("MPEG-2 422 Profile\n");
361 				break;
362 			case GPAC_OTI_VIDEO_MPEG1:
363 				info += wxT("MPEG-1\n");
364 				break;
365 			case GPAC_OTI_IMAGE_JPEG:
366 				info += wxT("JPEG\n");
367 				break;
368 			case GPAC_OTI_IMAGE_PNG:
369 				info += wxT("PNG\n");
370 				break;
371 			case GPAC_OTI_IMAGE_JPEG_2000:
372 				info += wxT("JPEG2000\n");
373 				break;
374 			case 0x80:
375 				memcpy(code, esd->decoderConfig->decoderSpecificInfo->data, 4);
376 				code[4] = 0;
377 				info += wxT("GPAC Intern (") + wxString(code, wxConvUTF8) + wxT(")\n");
378 				break;
379 			default:
380 				info += wxString::Format(wxT("Private/Unknown Type (0x%x)\n"), esd->decoderConfig->objectTypeIndication);
381 				break;
382 			}
383 			break;
384 
385 		case GF_STREAM_AUDIO:
386 			info += wxT("\tAudio Stream - media type: ");
387 			switch (esd->decoderConfig->objectTypeIndication) {
388 			case GPAC_OTI_AUDIO_AAC_MPEG4:
389 				info += wxT("MPEG-4\n");
390 				break;
391 			case GPAC_OTI_AUDIO_AAC_MPEG2_MP:
392 				info += wxT("MPEG-2 AAC Main Profile\n");
393 				break;
394 			case GPAC_OTI_AUDIO_AAC_MPEG2_LCP:
395 				info += wxT("MPEG-2 AAC LowComplexity Profile\n");
396 				break;
397 			case GPAC_OTI_AUDIO_AAC_MPEG2_SSRP:
398 				info += wxT("MPEG-2 AAC Scalable Sampling Rate Profile\n");
399 				break;
400 			case GPAC_OTI_AUDIO_MPEG2_PART3:
401 				info += wxT("MPEG-2 Audio\n");
402 				break;
403 			case GPAC_OTI_AUDIO_MPEG1:
404 				info += wxT("MPEG-1 Audio\n");
405 				break;
406 			case 0xA0:
407 				info += wxT("EVRC Audio\n");
408 				break;
409 			case 0xA1:
410 				info += wxT("SMV Audio\n");
411 				break;
412 			case 0xE1:
413 				info += wxT("QCELP Audio\n");
414 				break;
415 			case 0x80:
416 				memcpy(code, esd->decoderConfig->decoderSpecificInfo->data, 4);
417 				code[4] = 0;
418 				info += wxT("GPAC Intern (") + wxString(code, wxConvUTF8) + wxT(")\n");
419 				break;
420 			default:
421 				info += wxString::Format(wxT("Private/Unknown Type (0x%x)\n"), esd->decoderConfig->objectTypeIndication);
422 				break;
423 			}
424 			break;
425 		case GF_STREAM_MPEG7:
426 			info += wxString::Format(wxT("\tMPEG-7 Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
427 			break;
428 		case GF_STREAM_IPMP:
429 			info += wxString::Format(wxT("\tIPMP Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
430 			break;
431 		case GF_STREAM_OCI:
432 			info += wxString::Format(wxT("\tOCI Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
433 			break;
434 		case GF_STREAM_MPEGJ:
435 			info += wxString::Format(wxT("\tMPEGJ Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
436 			break;
437 		case GF_STREAM_INTERACT:
438 			info += wxString::Format(wxT("\tUser Interaction Stream - version %d\n"), esd->decoderConfig->objectTypeIndication);
439 			break;
440 		default:
441 			info += wxT("Private/Unknown\n");
442 			break;
443 		}
444 
445 		info += wxString::Format(wxT("\tBuffer Size %d\n\tAverage Bitrate %d bps\n\tMaximum Bitrate %d bps\n"), esd->decoderConfig->bufferSizeDB, esd->decoderConfig->avgBitrate, esd->decoderConfig->maxBitrate);
446 		if (esd->slConfig->predefined==SLPredef_SkipSL) {
447 			info += wxString::Format(wxT("\tNot using MPEG-4 Synchronization Layer\n"));
448 		} else {
449 			info += wxString::Format(wxT("\tStream Clock Resolution %d\n"), esd->slConfig->timestampResolution);
450 		}
451 		if (esd->URLString)
452 			info += wxT("\tStream Location: ") + wxString(esd->URLString, wxConvUTF8) + wxT("\n");
453 
454 		/*check language*/
455 		if (esd->langDesc) {
456 			s32 idx;
457 			char lan[4];
458 			lan[0] = esd->langDesc->langCode>>16;
459 			lan[1] = (esd->langDesc->langCode>>8)&0xFF;
460 			lan[2] = (esd->langDesc->langCode)&0xFF;
461 			lan[3] = 0;
462 			idx = gf_lang_find(lan);
463 			if (idx>=0) {
464 				info += wxString::Format(wxT("\tStream Language: %s\n"), gf_lang_get_name(idx) );
465 			}
466 		}
467 
468 	}
469 	m_pViewInfo->Clear();
470 	m_pViewInfo->AppendText(info);
471 }
472 
473 
SetDecoderInfo()474 void wxFileProps::SetDecoderInfo()
475 {
476 	GF_MediaInfo odi;
477 	wxString info;
478 	u32 h, m, s;
479 
480 	if (!m_current_odm || gf_term_get_object_info(m_pApp->m_term, m_current_odm, &odi)) {
481 		m_pViewInfo->Clear();
482 		m_pViewInfo->AppendText(info);
483 		return;
484 	}
485 
486 	info = wxT("Status: ");
487 	switch (odi.status) {
488 	case 0:
489 	case 1:
490 	case 2:
491 		h = (u32) (odi.current_time / 3600);
492 		m = (u32) (odi.current_time / 60) - h*60;
493 		s = (u32) (odi.current_time) - h*3600 - m*60;
494 		if (odi.status==0) info += wxT("Stopped");
495 		else if (odi.status==1) info += wxT("Playing");
496 		else info += wxT("Paused");
497 		info += wxString::Format(wxT("\nObject Time: %02d:%02d:%02d\n"), h, m, s);
498 		break;
499 	case 3:
500 		info += wxT("Not Setup\n");
501 		m_pViewInfo->Clear();
502 		m_pViewInfo->AppendText(info);
503 		return;
504 	default:
505 		info += wxT("Setup Failed\n");
506 		m_pViewInfo->Clear();
507 		m_pViewInfo->AppendText(info);
508 		return;
509 	}
510 	/*get clock drift*/
511 	info += wxString::Format(wxT("Clock drift: %d ms\n"), odi.clock_drift);
512 	/*get buffering*/
513 	if (odi.buffer>=0) info += wxString::Format(wxT("Buffering Time: %d ms\n"), odi.buffer);
514 	else if (odi.buffer==-1) info += wxT("Not buffering\n");
515 	else info += wxT("Not Playing\n");
516 
517 	/*get DB occupation*/
518 	if (odi.buffer>=0) info += wxString::Format(wxT("Decoding Buffer: %d Access Units\n"), odi.db_unit_count);
519 	/*get CB occupation*/
520 	if (odi.cb_max_count)
521 		info += wxString::Format(wxT("Composition Memory: %d/%d Units\n"), odi.cb_unit_count, odi.cb_max_count);
522 
523 	Float avg_dec_time = 0;
524 	if (odi.nb_dec_frames) {
525 		avg_dec_time = (Float) odi.total_dec_time;
526 		avg_dec_time /= odi.nb_dec_frames;
527 	}
528 	info += wxString::Format(wxT("Average Bitrate %d kbps (%d max)\nAverage Decoding Time %.2f ms (%d max)\nTotal decoded frames %d - %d dropped\n"),
529 	                         (u32) odi.avg_bitrate/1024, odi.max_bitrate/1024, avg_dec_time, odi.max_dec_time, odi.nb_dec_frames, odi.nb_dropped);
530 
531 	m_pViewInfo->Clear();
532 	m_pViewInfo->AppendText(info);
533 }
534 
SetNetworkInfo()535 void wxFileProps::SetNetworkInfo()
536 {
537 	wxString info;
538 	u32 id;
539 	NetStatCommand com;
540 	GF_MediaInfo odi;
541 	u32 d_enum;
542 	GF_Err e;
543 
544 	info = wxT("");
545 	m_pViewInfo->Clear();
546 	m_pViewInfo->AppendText(wxT(""));
547 
548 	if (!m_current_odm || gf_term_get_object_info(m_pApp->m_term, m_current_odm, &odi) != GF_OK) return;
549 
550 	if (odi.owns_service) {
551 		const char *url, *path;
552 		u32 done, total, bps;
553 		info = wxT("Current Downloads in service:\n");
554 		d_enum = 0;
555 		while (gf_term_get_download_info(m_pApp->m_term, m_current_odm, &d_enum, &url, &path, &done, &total, &bps)) {
556 			info += wxString(url, wxConvUTF8);
557 			if (total) {
558 				info += wxString::Format(wxT(": %d / %d bytes (%.2f %%) - %.2f kBps\n"), done, total, (100.0*done)/total, ((Double)bps)/1024);
559 			} else {
560 				info += wxString::Format(wxT(": %.2f kBps\n"), ((Double)bps)/1024);
561 			}
562 		}
563 		if (!d_enum) info = wxT("No Downloads in service\n");
564 		info += wxT("\n");
565 	}
566 
567 	d_enum = 0;
568 	while (gf_term_get_channel_net_info(m_pApp->m_term, m_current_odm, &d_enum, &id, &com, &e)) {
569 		if (e) continue;
570 		if (!com.bw_down && !com.bw_up) continue;
571 
572 		info += wxString::Format(wxT("Stream ID %d statistics:\n"), id);
573 		if (com.multiplex_port) {
574 			info += wxString::Format(wxT("\tMultiplex Port %d - multiplex ID %d\n"), com.multiplex_port, com.port);
575 		} else {
576 			info += wxString::Format(wxT("\tPort %d\n"), com.port);
577 		}
578 		info += wxString::Format(wxT("\tPacket Loss Percentage: %.4f\n"), com.pck_loss_percentage);
579 		info += wxString::Format(wxT("\tDown Bandwidth: %.3f bps\n"), ((Float)com.bw_down)/1024);
580 		if (com.bw_up) info += wxString::Format(wxT("\tUp Bandwidth: %d bps\n"), com.bw_up);
581 		if (com.ctrl_port) {
582 			if (com.multiplex_port) {
583 				info += wxString::Format(wxT("\tControl Multiplex Port: %d - Control Multiplex ID %d\n"), com.multiplex_port, com.ctrl_port);
584 			} else {
585 				info += wxString::Format(wxT("\tControl Port: %d\n"), com.ctrl_port);
586 			}
587 			info += wxString::Format(wxT("\tControl Down Bandwidth: %d bps\n"), com.ctrl_bw_down);
588 			info += wxString::Format(wxT("\tControl Up Bandwidth: %d bps\n"), com.ctrl_bw_up);
589 		}
590 		info += wxT("\n");
591 	}
592 	m_pViewInfo->Clear();
593 	m_pViewInfo->AppendText(info);
594 }
595 
596 
OnViewWorld(wxCommandEvent & WXUNUSED (event))597 void wxFileProps::OnViewWorld(wxCommandEvent &WXUNUSED(event))
598 {
599 	wxString wit;
600 	const char *str;
601 	GF_List *descs;
602 	descs = gf_list_new();
603 	str = gf_term_get_world_info(m_pApp->m_term, m_current_odm, descs);
604 
605 	if (!str) {
606 		wxMessageDialog(this, wxT("No World Info available"), wxT("Sorry!"), wxOK).ShowModal();
607 		return;
608 	}
609 
610 	wit = wxT("");
611 	for (u32 i=0; gf_list_count(descs); i++) {
612 		const char *d = (const char *) gf_list_get(descs, i);
613 		wit += wxString(d, wxConvUTF8);
614 		wit += wxT("\n");
615 	}
616 	wxMessageDialog(this, wit, wxString(str, wxConvUTF8), wxOK).ShowModal();
617 	gf_list_del(descs);
618 }
619 
OnViewSG(wxCommandEvent & WXUNUSED (event))620 void wxFileProps::OnViewSG(wxCommandEvent &WXUNUSED(event))
621 {
622 	const char *sOpt;
623 	Bool dump_xmt;
624 	wxFileName out_file;
625 	char szOutFile[GF_MAX_PATH];
626 	wxString fname;
627 
628 	sOpt = gf_cfg_get_key(m_pApp->m_user.config, "Core", "CacheDirectory");
629 	out_file.AssignDir(wxString(sOpt, wxConvUTF8) );
630 
631 	sOpt = gf_cfg_get_key(m_pApp->m_user.config, "General", "ViewXMT");
632 	out_file.SetFullName(wxT("scene_dump"));
633 	if (sOpt && !stricmp(sOpt, "yes")) {
634 		dump_xmt = 1;
635 	} else {
636 		dump_xmt = 0;
637 	}
638 	strcpy(szOutFile, out_file.GetFullName().mb_str(wxConvUTF8));
639 
640 	GF_Err e = gf_term_dump_scene(m_pApp->m_term, szOutFile, NULL, dump_xmt, 0, m_current_odm);
641 	if (e) {
642 		wxMessageDialog dlg(this, wxString(gf_error_to_string(e), wxConvUTF8), wxT("Error while dumping"), wxOK);
643 		dlg.ShowModal();
644 	} else {
645 		wxString cmd = get_pref_browser(m_pApp->m_user.config);
646 		cmd += wxT(" ");
647 		cmd += wxString(szOutFile, wxConvUTF8);
648 		wxExecute(cmd);
649 	}
650 }
651