xref: /haiku/src/apps/mediaplayer/InfoWin.cpp (revision f75a7bf508f3156d63a14f8fd77c5e0ca4d08c42)
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 400
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 + 300), NAME, B_TITLED_WINDOW,
82 		B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
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(" ");
227 	fContentsView->SetFontAndColor(be_plain_font, B_FONT_ALL);
228 //	fContentsView->Insert("");
229 
230 	if (!fController->Lock())
231 		return;
232 
233 	fLabelsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kRed);
234 
235 	status_t err;
236 	// video track format information
237 	if ((which & INFO_VIDEO) && fController->VideoTrackCount() > 0) {
238 		fLabelsView->Insert("Video\n\n\n\n");
239 		BString s;
240 		media_format format;
241 		media_raw_video_format videoFormat;
242 		err = fController->GetEncodedVideoFormat(&format);
243 		if (err < B_OK) {
244 			s << "(" << strerror(err) << ")\n";
245 		} else if (format.type == B_MEDIA_ENCODED_VIDEO) {
246 			videoFormat = format.u.encoded_video.output;
247 			media_codec_info mci;
248 			err = fController->GetVideoCodecInfo(&mci);
249 			if (err < B_OK) {
250 				s << "Haiku Media Kit:\n(" << strerror(err) << ")";
251 				if (format.user_data_type == B_CODEC_TYPE_INFO) {
252 					s << (char *)format.user_data << " not supported";
253 				}
254 			} else
255 				s << mci.pretty_name; //<< "(" << mci.short_name << ")";
256 		} else if (format.type == B_MEDIA_RAW_VIDEO) {
257 			videoFormat = format.u.raw_video;
258 			s << "raw video";
259 		} else
260 			s << "unknown format";
261 		s << "\n";
262 		s << format.Width() << " x " << format.Height();
263 		// encoded has output as 1st field...
264 		s << ", " << videoFormat.field_rate << " fps";
265 		s << "\n\n";
266 		fContentsView->Insert(s.String());
267 	}
268 
269 	// audio track format information
270 	if ((which & INFO_AUDIO) && fController->AudioTrackCount() > 0) {
271 		fLabelsView->Insert("Audio\n\n\n\n");
272 		BString s;
273 		media_format format;
274 		media_raw_audio_format audioFormat;
275 		err = fController->GetEncodedAudioFormat(&format);
276 		//string_for_format(format, buf, sizeof(buf));
277 		//printf("%s\n", buf);
278 		if (err < 0) {
279 			s << "(" << strerror(err) << ")\n";
280 		} else if (format.type == B_MEDIA_ENCODED_AUDIO) {
281 			audioFormat = format.u.encoded_audio.output;
282 			media_codec_info mci;
283 			err = fController->GetAudioCodecInfo(&mci);
284 			if (err < 0) {
285 				s << "Haiku Media Kit:\n(" << strerror(err) << ") ";
286 				if (format.user_data_type == B_CODEC_TYPE_INFO) {
287 					s << (char *)format.user_data << " not supported";
288 				}
289 			} else
290 				s << mci.pretty_name; //<< "(" << mci.short_name << ")";
291 		} else if (format.type == B_MEDIA_RAW_AUDIO) {
292 			audioFormat = format.u.raw_audio;
293 			s << "raw audio";
294 		} else
295 			s << "unknown format";
296 		s << "\n";
297 		uint32 bitsPerSample = 8 * (audioFormat.format
298 			& media_raw_audio_format::B_AUDIO_SIZE_MASK);
299 		uint32 channelCount = audioFormat.channel_count;
300 		float sr = audioFormat.frame_rate;
301 
302 		if (bitsPerSample > 0)
303 			s << bitsPerSample << " Bit ";
304 		if (channelCount == 1)
305 			s << "Mono";
306 		else if (channelCount == 2)
307 			s << "Stereo";
308 		else
309 			s << channelCount << " Channels";
310 		s << ", ";
311 		if (sr > 0.0)
312 			s << sr / 1000;
313 		else
314 			s << "??";
315 		s<< " kHz";
316 		s << "\n\n";
317 		fContentsView->Insert(s.String());
318 	}
319 
320 	// statistics
321 	if ((which & INFO_STATS) && fController->HasFile()) {
322 		fLabelsView->Insert("Duration\n");
323 		BString s;
324 		bigtime_t d = fController->TimeDuration();
325 		bigtime_t v;
326 
327 		//s << d << "µs; ";
328 
329 		d /= 1000;
330 
331 		v = d / (3600 * 1000);
332 		d = d % (3600 * 1000);
333 		bool hours = v > 0;
334 		if (hours)
335 			s << v << ":";
336 		v = d / (60 * 1000);
337 		d = d % (60 * 1000);
338 		s << v << ":";
339 		v = d / 1000;
340 		s << v;
341 		if (hours)
342 			s << " h";
343 		else
344 			s << " min";
345 		s << "\n";
346 		fContentsView->Insert(s.String());
347 		// TODO: demux/video/audio/... perfs (Kb/s)
348 
349 		fLabelsView->Insert("Display Mode\n");
350 		if (fController->IsOverlayActive())
351 			fContentsView->Insert("Overlay\n");
352 		else
353 			fContentsView->Insert("DrawBitmap\n");
354 
355 		fLabelsView->Insert("\n");
356 		fContentsView->Insert("\n\n");
357 	}
358 
359 	if (which & INFO_TRANSPORT) {
360 		// Transport protocol info (file, http, rtsp, ...)
361 	}
362 
363 	if (which & INFO_FILE) {
364 		if (fController->HasFile()) {
365 			media_file_format ff;
366 			BString s;
367 			if (fController->GetFileFormatInfo(&ff) == B_OK) {
368 				fLabelsView->Insert("Container\n");
369 				s << ff.pretty_name;
370 				s << "\n";
371 				fContentsView->Insert(s.String());
372 			} else
373 				fContentsView->Insert("\n");
374 			fLabelsView->Insert("Location\n");
375 			if (fController->GetLocation(&s) < B_OK)
376 				s = "<unknown>";
377 			s << "\n";
378 			fContentsView->Insert(s.String());
379 			if (fController->GetName(&s) < B_OK)
380 				s = "<unnamed media>";
381 			fFilenameView->SetText(s.String());
382 		} else {
383 			fFilenameView->SetText("<no media>");
384 		}
385 	}
386 
387 	if ((which & INFO_COPYRIGHT) && fController->HasFile()) {
388 
389 		BString s;
390 		if (fController->GetCopyright(&s) == B_OK && s.Length() > 0) {
391 			fLabelsView->Insert("Copyright\n\n");
392 			s << "\n\n";
393 			fContentsView->Insert(s.String());
394 		}
395 	}
396 
397 	fController->Unlock();
398 
399 	ResizeToPreferred();
400 }
401