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