xref: /haiku/src/apps/mediaplayer/InfoWin.cpp (revision 89755088d790ff4fe36f8aa77dacb2bd15507108)
1 /*
2  * InfoWin.cpp - Media Player for the Haiku Operating System
3  *
4  * Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  */
20 #include "InfoWin.h"
21 
22 #include <math.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include <Debug.h>
27 #include <MediaDefs.h>
28 #include <String.h>
29 #include <StringView.h>
30 #include <TextView.h>
31 
32 #include "Controller.h"
33 #include "ControllerObserver.h"
34 
35 
36 #define NAME "File Info"
37 #define MIN_WIDTH 350
38 
39 #define BASE_HEIGHT (32 + 32)
40 
41 //const rgb_color kGreen = { 152, 203, 152, 255 };
42 const rgb_color kRed =   { 203, 152, 152, 255 };
43 const rgb_color kBlue =  {   0,   0, 220, 255 };
44 const rgb_color kGreen = { 171, 221, 161, 255 };
45 const rgb_color kBlack = {   0,   0,   0, 255 };
46 
47 
48 // should later draw an icon
49 class InfoView : public BView {
50 public:
51 	InfoView(BRect frame, const char *name, float divider)
52 		: BView(frame, name, B_FOLLOW_ALL,
53 			B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE)
54 		, fDivider(divider)
55 		{ }
56 	virtual ~InfoView()
57 		{ }
58 	void Draw(BRect updateRect);
59 	float fDivider;
60 };
61 
62 
63 void
64 InfoView::Draw(BRect updateRect)
65 {
66 	SetHighColor(kGreen);
67 	BRect r(Bounds());
68 	r.right = r.left + fDivider;
69 	FillRect(r);
70 	SetHighColor(ui_color(B_DOCUMENT_TEXT_COLOR));
71 	r.left = r.right;
72 	FillRect(r);
73 }
74 
75 
76 // #pragma mark -
77 
78 
79 InfoWin::InfoWin(BPoint leftTop, Controller* controller)
80 	: BWindow(BRect(leftTop.x, leftTop.y, leftTop.x + MIN_WIDTH - 1,
81 		leftTop.y + 250), NAME, B_TITLED_WINDOW,
82 		B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE)
83 	, fController(controller)
84 	, fControllerObserver(new ControllerObserver(this,
85 		OBSERVE_FILE_CHANGES | OBSERVE_TRACK_CHANGES | OBSERVE_STAT_CHANGES))
86 {
87 	BRect rect = Bounds();
88 
89 	// accomodate for big fonts
90 	float div = max_c(2 * 32, be_plain_font->StringWidth("Display Mode") + 10);
91 
92 	fInfoView = new InfoView(rect, "background", div);
93 	fInfoView->SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
94 	AddChild(fInfoView);
95 
96 	BFont bigFont(be_plain_font);
97 	bigFont.SetSize(bigFont.Size() + 6);
98 	font_height fh;
99 	bigFont.GetHeight(&fh);
100 	fFilenameView = new BStringView(BRect(div + 10, 20,
101 										  rect.right - 10,
102 										  20 + fh.ascent + 5),
103 									"filename", "");
104 	fFilenameView->SetFont(&bigFont);
105 	fFilenameView->SetViewColor(fInfoView->ViewColor());
106 	fFilenameView->SetLowColor(fInfoView->ViewColor());
107 #ifdef B_BEOS_VERSION_DANO /* maybe we should support that as well ? */
108 	fFilenameView->SetTruncation(B_TRUNCATE_END);
109 #endif
110 	AddChild(fFilenameView);
111 
112 
113 	rect.top = BASE_HEIGHT;
114 
115 	BRect lr(rect);
116 	BRect cr(rect);
117 	lr.right = div - 1;
118 	cr.left = div + 1;
119 	BRect tr;
120 	tr = lr.OffsetToCopy(0, 0).InsetByCopy(5, 1);
121 	fLabelsView = new BTextView(lr, "labels", tr, B_FOLLOW_BOTTOM);
122 	fLabelsView->SetViewColor(kGreen);
123 	fLabelsView->SetAlignment(B_ALIGN_RIGHT);
124 	fLabelsView->SetWordWrap(false);
125 	AddChild(fLabelsView);
126 	tr = cr.OffsetToCopy(0, 0).InsetByCopy(10, 1);
127 	fContentsView = new BTextView(cr, "contents", tr, B_FOLLOW_BOTTOM);
128 	fContentsView->SetWordWrap(false);
129 	AddChild(fContentsView);
130 
131 	fLabelsView->MakeSelectable();
132 	fContentsView->MakeSelectable();
133 
134 	fController->AddListener(fControllerObserver);
135 	Update();
136 
137 	Show();
138 }
139 
140 
141 InfoWin::~InfoWin()
142 {
143 	fController->RemoveListener(fControllerObserver);
144 	delete fControllerObserver;
145 
146 	//fInfoListView->MakeEmpty();
147 	//delete [] fInfoItems;
148 }
149 
150 
151 // #pragma mark -
152 
153 
154 void
155 InfoWin::FrameResized(float new_width, float new_height)
156 {
157 }
158 
159 
160 void
161 InfoWin::MessageReceived(BMessage *msg)
162 {
163 	switch (msg->what) {
164 		case MSG_CONTROLLER_FILE_FINISHED:
165 			break;
166 		case MSG_CONTROLLER_FILE_CHANGED:
167 			Update(INFO_ALL);
168 			break;
169 		case MSG_CONTROLLER_VIDEO_TRACK_CHANGED:
170 			Update(/*INFO_VIDEO | INFO_STATS*/INFO_ALL);
171 			break;
172 		case MSG_CONTROLLER_AUDIO_TRACK_CHANGED:
173 			Update(/*INFO_AUDIO | INFO_STATS*/INFO_ALL);
174 			break;
175 		case MSG_CONTROLLER_VIDEO_STATS_CHANGED:
176 		case MSG_CONTROLLER_AUDIO_STATS_CHANGED:
177 			Update(/*INFO_STATS*/INFO_ALL);
178 			break;
179 		default:
180 			BWindow::MessageReceived(msg);
181 			break;
182 	}
183 }
184 
185 
186 bool
187 InfoWin::QuitRequested()
188 {
189 	Hide();
190 	return false;
191 }
192 
193 
194 void
195 InfoWin::Pulse()
196 {
197 	if (IsHidden())
198 		return;
199 	Update(INFO_STATS);
200 }
201 
202 
203 // #pragma mark -
204 
205 
206 void
207 InfoWin::ResizeToPreferred()
208 {
209 #if 0
210 	float height = BASE_HEIGHT;
211 	for (int i = 0; BListItem *li = fInfoListView->ItemAt(i); i++) {
212 		height += li->Height();
213 	}
214 	ResizeTo(Bounds().Width(), height);
215 #endif
216 }
217 
218 
219 void
220 InfoWin::Update(uint32 which)
221 {
222 printf("InfoWin::Update(0x%08lx)\n", which);
223 	fLabelsView->SetText("");
224 	fContentsView->SetText("");
225 	fLabelsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kBlue);
226 	fLabelsView->Insert("\n");
227 	fContentsView->SetFontAndColor(be_plain_font, B_FONT_ALL);
228 	fContentsView->Insert("\n");
229 
230 	fLabelsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kRed);
231 
232 	status_t err;
233 	// video track format information
234 	if ((which & INFO_VIDEO) && fController->VideoTrackCount() > 0) {
235 		fLabelsView->Insert("Video\n\n\n");
236 		BString s;
237 		media_format format;
238 		media_raw_video_format videoFormat;
239 		err = fController->GetEncodedVideoFormat(&format);
240 		if (err < B_OK) {
241 			s << "(" << strerror(err) << ")";
242 		} else if (format.type == B_MEDIA_ENCODED_VIDEO) {
243 			videoFormat = format.u.encoded_video.output;
244 			media_codec_info mci;
245 			err = fController->GetVideoCodecInfo(&mci);
246 			if (err < B_OK)
247 				s << "(" << strerror(err) << ")";
248 			else
249 				s << mci.pretty_name; //<< "(" << mci.short_name << ")";
250 		} else if (format.type == B_MEDIA_RAW_VIDEO) {
251 			videoFormat = format.u.raw_video;
252 			s << "raw video";
253 		} else
254 			s << "unknown format";
255 		s << "\n";
256 		s << format.Width() << " x " << format.Height();
257 		// encoded has output as 1st field...
258 		s << ", " << videoFormat.field_rate << " fps";
259 		s << "\n\n";
260 		fContentsView->Insert(s.String());
261 	}
262 
263 	// audio track format information
264 	if ((which & INFO_AUDIO) && fController->AudioTrackCount() > 0) {
265 		fLabelsView->Insert("Audio\n\n\n");
266 		BString s;
267 		media_format format;
268 		media_raw_audio_format audioFormat;
269 		err = fController->GetEncodedAudioFormat(&format);
270 		//string_for_format(format, buf, sizeof(buf));
271 		//printf("%s\n", buf);
272 		if (err < 0) {
273 			s << "(" << strerror(err) << ")";
274 		} else if (format.type == B_MEDIA_ENCODED_AUDIO) {
275 			audioFormat = format.u.encoded_audio.output;
276 			media_codec_info mci;
277 			err = fController->GetAudioCodecInfo(&mci);
278 			if (err < 0)
279 				s << "(" << strerror(err) << ")";
280 			else
281 				s << mci.pretty_name; //<< "(" << mci.short_name << ")";
282 		} else if (format.type == B_MEDIA_RAW_AUDIO) {
283 			audioFormat = format.u.raw_audio;
284 			s << "raw audio";
285 		} else
286 			s << "unknown format";
287 		s << "\n";
288 		uint32 bitsPerSample = 8 * (audioFormat.format
289 			& media_raw_audio_format::B_AUDIO_SIZE_MASK);
290 		uint32 channelCount = audioFormat.channel_count;
291 		float sr = audioFormat.frame_rate;
292 
293 		if (bitsPerSample > 0)
294 			s << bitsPerSample << " Bit ";
295 		if (channelCount == 1)
296 			s << "Mono";
297 		else if (channelCount == 2)
298 			s << "Stereo";
299 		else
300 			s << channelCount << "Channels";
301 		s << ", ";
302 		if (sr > 0.0)
303 			s << sr / 1000;
304 		else
305 			s << "??";
306 		s<< " kHz";
307 		s << "\n\n";
308 		fContentsView->Insert(s.String());
309 	}
310 
311 	// statistics
312 	if ((which & INFO_STATS) && fController->HasFile()) {
313 		fLabelsView->Insert("Duration\n");
314 		BString s;
315 		bigtime_t d = fController->Duration();
316 		bigtime_t v;
317 
318 		//s << d << "µs; ";
319 
320 		d /= 1000;
321 
322 		v = d / (3600 * 1000);
323 		d = d % (3600 * 1000);
324 		bool hours = v > 0;
325 		if (hours)
326 			s << v << ":";
327 		v = d / (60 * 1000);
328 		d = d % (60 * 1000);
329 		s << v << ":";
330 		v = d / 1000;
331 		s << v;
332 		if (hours)
333 			s << " h";
334 		else
335 			s << " min";
336 		s << "\n";
337 		fContentsView->Insert(s.String());
338 		// TODO: demux/video/audio/... perfs (Kb/s)
339 
340 		fLabelsView->Insert("Display Mode\n");
341 		if (fController->IsOverlayActive())
342 			fContentsView->Insert("Overlay\n");
343 		else
344 			fContentsView->Insert("DrawBitmap\n");
345 
346 		fLabelsView->Insert("\n");
347 		fContentsView->Insert("\n");
348 	}
349 
350 	if (which & INFO_TRANSPORT) {
351 		// Transport protocol info (file, http, rtsp, ...)
352 	}
353 
354 	if (which & INFO_FILE) {
355 		if (fController->HasFile()) {
356 			media_file_format ff;
357 			BString s;
358 			if (fController->GetFileFormatInfo(&ff) == B_OK) {
359 				fLabelsView->Insert("Container\n\n");
360 				s << ff.pretty_name;
361 				s << "\n\n";
362 				fContentsView->Insert(s.String());
363 			} else
364 				fContentsView->Insert("\n\n");
365 			fLabelsView->Insert("Location\n");
366 			if (fController->GetLocation(&s) < B_OK)
367 				s = "<unknown>";
368 			s << "\n";
369 			fContentsView->Insert(s.String());
370 			if (fController->GetName(&s) < B_OK)
371 				s = "<unnamed media>";
372 			fFilenameView->SetText(s.String());
373 		} else {
374 			fFilenameView->SetText("<no media>");
375 		}
376 	}
377 
378 	if ((which & INFO_COPYRIGHT) && fController->HasFile()) {
379 
380 		BString s;
381 		if (fController->GetCopyright(&s) == B_OK && s.Length() > 0) {
382 			fLabelsView->Insert("Copyright\n\n");
383 			s << "\n\n";
384 			fContentsView->Insert(s.String());
385 		}
386 	}
387 
388 	fController->Unlock();
389 
390 	ResizeToPreferred();
391 }
392 
393 
394 
395 
396