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