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 <View.h> 23 #include <stdio.h> 24 #include <string.h> 25 #include <String.h> 26 #include <Debug.h> 27 #include <MediaDefs.h> 28 #include <MediaFile.h> 29 #include <MediaTrack.h> 30 #include <TextView.h> 31 #include <math.h> 32 #include "MainWin.h" 33 34 #define NAME "File Info" 35 #define MIN_WIDTH 350 36 37 #define BASE_HEIGHT (32+32) 38 39 //const rgb_color kGreen = { 152, 203, 152, 255 }; 40 const rgb_color kRed = { 203, 152, 152, 255 }; 41 const rgb_color kBlue = { 0, 0, 220, 255 }; 42 const rgb_color kGreen = { 171, 221, 161, 255 }; 43 const rgb_color kBlack = { 0, 0, 0, 255 }; 44 45 46 // should later draw an icon 47 class InfoView : public BView { 48 public: 49 InfoView(BRect frame, const char *name, float divider) 50 : BView(frame, name, B_FOLLOW_ALL, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE) 51 , fDivider(divider) 52 { } 53 virtual ~InfoView() 54 { } 55 void Draw(BRect updateRect); 56 float fDivider; 57 }; 58 59 60 void 61 InfoView::Draw(BRect updateRect) 62 { 63 SetHighColor(kGreen); 64 BRect r(Bounds()); 65 r.right = r.left + fDivider; 66 FillRect(r); 67 SetHighColor(ui_color(B_DOCUMENT_TEXT_COLOR)); 68 r.left = r.right; 69 FillRect(r); 70 } 71 72 73 InfoWin::InfoWin(MainWin *mainWin) 74 : BWindow(BRect(100,100,100+MIN_WIDTH-1,350), NAME, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE /* | B_WILL_ACCEPT_FIRST_CLICK */), 75 fMainWin(mainWin), 76 fController() 77 { 78 BRect rect; 79 if (fMainWin->Lock()) { 80 rect = fMainWin->Frame(); 81 MoveTo(rect.right, rect.top); 82 fMainWin->Unlock(); 83 } 84 85 rect = Bounds(); 86 87 // accomodate for big fonts 88 float div; 89 div = MAX(2*32, be_plain_font->StringWidth("Container") + 5); 90 91 fInfoView = new InfoView(rect, "background", div); 92 fInfoView->SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR)); 93 AddChild(fInfoView); 94 95 BFont bigFont(be_plain_font); 96 bigFont.SetSize(bigFont.Size()+6); 97 font_height fh; 98 bigFont.GetHeight(&fh); 99 fFilenameView = new BStringView(BRect(div+10, 20, 100 rect.right - 10, 101 20 + fh.ascent + 5), 102 "filename", ""); 103 fFilenameView->SetFont(&bigFont); 104 fFilenameView->SetViewColor(fInfoView->ViewColor()); 105 fFilenameView->SetLowColor(fInfoView->ViewColor()); 106 #ifdef B_BEOS_VERSION_DANO /* maybe we should support that as well ? */ 107 fFilenameView->SetTruncation(B_TRUNCATE_END); 108 #endif 109 AddChild(fFilenameView); 110 111 112 rect.top = BASE_HEIGHT; 113 114 BRect lr(rect); 115 BRect cr(rect); 116 lr.right = div - 1; 117 cr.left = div + 1; 118 BRect tr; 119 tr = lr.OffsetToCopy(0,0).InsetByCopy(1,1); 120 fLabelsView = new BTextView(lr, "labels", tr, B_FOLLOW_BOTTOM); 121 fLabelsView->SetViewColor(kGreen); 122 fLabelsView->SetAlignment(B_ALIGN_RIGHT); 123 fLabelsView->SetWordWrap(false); 124 AddChild(fLabelsView); 125 tr = cr.OffsetToCopy(0,0).InsetByCopy(1,1); 126 fContentsView = new BTextView(cr, "contents", tr, B_FOLLOW_BOTTOM); 127 fContentsView->SetWordWrap(false); 128 AddChild(fContentsView); 129 130 fLabelsView->MakeSelectable(); 131 fContentsView->MakeSelectable(); 132 133 134 Show(); 135 } 136 137 138 InfoWin::~InfoWin() 139 { 140 printf("InfoWin::~InfoWin\n"); 141 //fInfoListView->MakeEmpty(); 142 //delete [] fInfoItems; 143 } 144 145 146 void 147 InfoWin::ResizeToPreferred() 148 { 149 #if 0 150 int i; 151 float height = BASE_HEIGHT; 152 BListItem *li; 153 for (i = 0; (li = fInfoListView->ItemAt(i)); i++) { 154 height += li->Height(); 155 } 156 ResizeTo(Bounds().Width(), height); 157 #endif 158 } 159 160 161 void 162 InfoWin::Update(uint32 which) 163 { 164 status_t err; 165 //char buf[256]; 166 printf("InfoWin::Update(0x%08lx)\n", which); 167 rgb_color vFgCol = ui_color(B_DOCUMENT_TEXT_COLOR); 168 169 fLabelsView->SelectAll(); 170 fContentsView->SelectAll(); 171 fLabelsView->Clear(); 172 fContentsView->Clear(); 173 fLabelsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kBlue); 174 fLabelsView->Insert("File Info\n"); 175 fContentsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &vFgCol); 176 fContentsView->Insert("\n"); 177 178 fLabelsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &kRed); 179 //fContentsView->SetFontAndColor(be_plain_font, B_FONT_ALL, &vFgCol); 180 181 // lock the Main Window as we must access some fields there... 182 if (fMainWin->LockWithTimeout(500000) < B_OK) 183 return; // XXX: resend msg to ourselves ? 184 185 Controller *c = fMainWin->fController; 186 BMediaFile *mf = c->fMediaFile; 187 188 if (which & INFO_VIDEO && c->VideoTrackCount() > 0) { 189 fLabelsView->Insert("Video\n\n"); 190 BString s; 191 media_format fmt; 192 media_raw_video_format vfmt; 193 float fps; 194 err = c->fVideoTrack->EncodedFormat(&fmt); 195 //string_for_format(fmt, buf, sizeof(buf)); 196 //printf("%s\n", buf); 197 if (err < 0) { 198 s << "(" << strerror(err) << ")"; 199 } else if (fmt.type == B_MEDIA_ENCODED_VIDEO) { 200 vfmt = fmt.u.encoded_video.output; 201 media_codec_info mci; 202 err = c->fVideoTrack->GetCodecInfo(&mci); 203 if (err < 0) 204 s << "(" << strerror(err) << ")"; 205 else 206 s << mci.pretty_name; //<< "(" << mci.short_name << ")"; 207 } else if (fmt.type == B_MEDIA_RAW_VIDEO) { 208 vfmt = fmt.u.raw_video; 209 s << "raw video"; 210 } else 211 s << "unknown format"; 212 s << "\n"; 213 s << fmt.Width() << " x " << fmt.Height(); 214 // encoded has output as 1st field... 215 fps = vfmt.field_rate; 216 s << ", " << fps << " fps"; 217 s << "\n"; 218 fContentsView->Insert(s.String()); 219 } 220 if (which & INFO_AUDIO && c->AudioTrackCount() > 0) { 221 fLabelsView->Insert("Sound\n\n"); 222 BString s; 223 media_format fmt; 224 media_raw_audio_format afmt; 225 err = c->fAudioTrack->EncodedFormat(&fmt); 226 //string_for_format(fmt, buf, sizeof(buf)); 227 //printf("%s\n", buf); 228 if (err < 0) { 229 s << "(" << strerror(err) << ")"; 230 } else if (fmt.type == B_MEDIA_ENCODED_AUDIO) { 231 afmt = fmt.u.encoded_audio.output; 232 media_codec_info mci; 233 err = c->fAudioTrack->GetCodecInfo(&mci); 234 if (err < 0) 235 s << "(" << strerror(err) << ")"; 236 else 237 s << mci.pretty_name; //<< "(" << mci.short_name << ")"; 238 } else if (fmt.type == B_MEDIA_RAW_AUDIO) { 239 afmt = fmt.u.raw_audio; 240 s << "raw audio"; 241 } else 242 s << "unknown format"; 243 s << "\n"; 244 uint32 bitps = 8 * (afmt.format & media_raw_audio_format::B_AUDIO_SIZE_MASK); 245 uint32 chans = afmt.channel_count; 246 float sr = afmt.frame_rate; 247 248 if (bitps) 249 s << bitps << " Bit "; 250 if (chans == 1) 251 s << "Mono"; 252 else if (chans == 2) 253 s << "Stereo"; 254 else 255 s << chans << "Channels"; 256 s << ", "; 257 if (sr) 258 s << sr/1000; 259 else 260 s << "?"; 261 s<< " kHz"; 262 s << "\n"; 263 fContentsView->Insert(s.String()); 264 } 265 if (which & INFO_STATS && fMainWin->fHasFile) { 266 // TODO: check for live streams (no duration) 267 fLabelsView->Insert("Duration\n"); 268 BString s; 269 bigtime_t d = c->Duration(); 270 bigtime_t v; 271 272 //s << d << "µs; "; 273 274 d /= 1000; 275 276 v = d / (3600 * 1000); 277 d = d % (3600 * 1000); 278 if (v) 279 s << v << ":"; 280 v = d / (60 * 1000); 281 d = d % (60 * 1000); 282 s << v << ":"; 283 v = d / 1000; 284 d = d % 1000; 285 s << v; 286 if (d) 287 s << "." << d / 10; 288 s << "\n"; 289 fContentsView->Insert(s.String()); 290 // TODO: demux/video/audio/... perfs (Kb/s) 291 } 292 if (which & INFO_TRANSPORT) { 293 } 294 if ((which & INFO_FILE) && fMainWin->fHasFile) { 295 media_file_format ff; 296 if (mf && (mf->GetFileFormatInfo(&ff) == B_OK)) { 297 fLabelsView->Insert("Container\n"); 298 BString s; 299 s << ff.pretty_name; 300 s << "\n"; 301 fContentsView->Insert(s.String()); 302 } 303 fLabelsView->Insert("Location\n"); 304 // TODO: make Controller save the entry_ref (url actually). 305 fContentsView->Insert("file://\n"); 306 fFilenameView->SetText(c->fName.String()); 307 } 308 if (which & INFO_COPYRIGHT && mf && mf->Copyright()) { 309 310 fLabelsView->Insert("Copyright\n\n"); 311 BString s; 312 s << mf->Copyright(); 313 s << "\n\n"; 314 fContentsView->Insert(s.String()); 315 } 316 317 // we can unlock the main window now and let it work 318 fMainWin->Unlock(); 319 320 // now resize the window to the list view size... 321 ResizeToPreferred(); 322 323 if (IsHidden()) 324 Show(); 325 } 326 327 328 bool 329 InfoWin::QuitRequested() 330 { 331 Hide(); 332 return false; 333 } 334 335 336 void 337 InfoWin::Show() 338 { 339 // notify the main window first 340 fMainWin->fInfoWinShowing = true; 341 BWindow::Show(); 342 //SetPulseRate(1000000); 343 } 344 345 346 void 347 InfoWin::Hide() 348 { 349 SetPulseRate(0); 350 BWindow::Hide(); 351 fMainWin->fInfoWinShowing = false; 352 } 353 354 355 void 356 InfoWin::Pulse() 357 { 358 if (IsHidden()) 359 return; 360 Update(INFO_STATS); 361 } 362 363 void 364 InfoWin::FrameResized(float new_width, float new_height) 365 { 366 #if 0 367 if (new_width != Bounds().Width() || new_height != Bounds().Height()) { 368 debugger("size wrong\n"); 369 } 370 371 bool no_menu = fNoMenu || fIsFullscreen; 372 bool no_controls = fNoControls || fIsFullscreen; 373 374 printf("FrameResized enter: new_width %.0f, new_height %.0f\n", new_width, new_height); 375 376 int max_video_width = int(new_width) + 1; 377 int max_video_height = int(new_height) + 1 - (no_menu ? 0 : fMenuBarHeight) - (no_controls ? 0 : fControlsHeight); 378 379 ASSERT(max_video_height >= 0); 380 381 int y = 0; 382 383 if (no_menu) { 384 if (!fMenuBar->IsHidden()) 385 fMenuBar->Hide(); 386 } else { 387 // fMenuBar->MoveTo(0, y); 388 fMenuBar->ResizeTo(new_width, fMenuBarHeight - 1); 389 if (fMenuBar->IsHidden()) 390 fMenuBar->Show(); 391 y += fMenuBarHeight; 392 } 393 394 if (max_video_height == 0) { 395 if (!fVideoView->IsHidden()) 396 fVideoView->Hide(); 397 } else { 398 // fVideoView->MoveTo(0, y); 399 // fVideoView->ResizeTo(max_video_width - 1, max_video_height - 1); 400 ResizeVideoView(0, y, max_video_width, max_video_height); 401 if (fVideoView->IsHidden()) 402 fVideoView->Show(); 403 y += max_video_height; 404 } 405 406 if (no_controls) { 407 if (!fControls->IsHidden()) 408 fControls->Hide(); 409 } else { 410 fControls->MoveTo(0, y); 411 fControls->ResizeTo(new_width, fControlsHeight - 1); 412 if (fControls->IsHidden()) 413 fControls->Show(); 414 // y += fControlsHeight; 415 } 416 #endif 417 418 printf("FrameResized leave\n"); 419 } 420 421 422 void 423 InfoWin::MessageReceived(BMessage *msg) 424 { 425 uint32 which; 426 switch (msg->what) { 427 case M_UPDATE_INFO: 428 if (msg->FindInt32("which", (int32 *)&which) < B_OK) 429 which = INFO_ALL; 430 Update(which); 431 break; 432 default: 433 BWindow::MessageReceived(msg); 434 break; 435 } 436 } 437