1 // Copyright 1999, Be Incorporated. All Rights Reserved. 2 // Copyright 2000-2004, Jun Suzuki. All Rights Reserved. 3 // Copyright 2007, Stephan Aßmus. All Rights Reserved. 4 // This file may be used under the terms of the Be Sample Code License. 5 #include "MediaConverterWindow.h" 6 7 #include <stdio.h> 8 #include <string.h> 9 10 #include <Alert.h> 11 #include <Application.h> 12 #include <Box.h> 13 #include <Button.h> 14 #include <FilePanel.h> 15 #include <Menu.h> 16 #include <MenuBar.h> 17 #include <MenuField.h> 18 #include <MenuItem.h> 19 #include <Path.h> 20 #include <PopUpMenu.h> 21 #include <Roster.h> 22 #include <ScrollBar.h> 23 #include <ScrollView.h> 24 #include <Slider.h> 25 #include <StringView.h> 26 #include <TextControl.h> 27 28 #include "MediaFileInfoView.h" 29 #include "MediaFileListView.h" 30 #include "MessageConstants.h" 31 #include "StatusView.h" 32 #include "Strings.h" 33 34 35 // #pragma mark - DirectoryFilter 36 37 38 class DirectoryFilter : public BRefFilter 39 { 40 public: 41 DirectoryFilter(){}; 42 virtual bool Filter(const entry_ref *ref, 43 BNode *node, struct stat *st, const char *filetype) 44 { 45 return node->IsDirectory(); 46 } 47 private: 48 }; 49 50 51 // #pragma mark - FileFormatMenuItem 52 53 54 class FileFormatMenuItem : public BMenuItem { 55 public: 56 FileFormatMenuItem(media_file_format* format); 57 virtual ~FileFormatMenuItem(); 58 59 media_file_format fFileFormat; 60 }; 61 62 63 FileFormatMenuItem::FileFormatMenuItem(media_file_format *format) 64 : BMenuItem(format->pretty_name, new BMessage(FORMAT_SELECT_MESSAGE)) 65 { 66 memcpy(&fFileFormat, format, sizeof(fFileFormat)); 67 } 68 69 70 FileFormatMenuItem::~FileFormatMenuItem() 71 { 72 } 73 74 75 // #pragma mark - CodecMenuItem 76 77 78 class CodecMenuItem : public BMenuItem { 79 public: 80 CodecMenuItem(media_codec_info *ci, uint32 msg_type); 81 virtual ~CodecMenuItem(); 82 83 media_codec_info fCodecInfo; 84 }; 85 86 87 CodecMenuItem::CodecMenuItem(media_codec_info *ci, uint32 msg_type) 88 : BMenuItem(ci->pretty_name, new BMessage(msg_type)) 89 { 90 memcpy(&fCodecInfo, ci, sizeof(fCodecInfo)); 91 } 92 93 94 CodecMenuItem::~CodecMenuItem() 95 { 96 } 97 98 99 // #pragma mark - MediaConverterWindow 100 101 102 MediaConverterWindow::MediaConverterWindow(BRect frame) 103 : BWindow(frame, "MediaConverter", B_TITLED_WINDOW_LOOK, 104 B_NORMAL_WINDOW_FEEL, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS) 105 106 , fVideoQuality(75) 107 , fAudioQuality(75) 108 109 , fSaveFilePanel(NULL) 110 , fOpenFilePanel(NULL) 111 112 , fOutputDirSpecified(false) 113 114 , fEnabled(true) 115 , fConverting(false) 116 , fCancelling(false) 117 { 118 char defaultdirectory[] = "/boot/home"; 119 fOutputDir.SetTo(defaultdirectory); 120 121 #if B_BEOS_VERSION >= 0x530 // 0x520 RC2 0x530 RC3 122 // load Locale files for ZETA 123 entry_ref mypath; 124 app_info info; 125 126 be_app->GetAppInfo(&info); 127 mypath = info.ref; 128 129 BPath path(&mypath); 130 path.GetParent(&path); 131 path.Append("Language/Dictionaries"); 132 path.Append("MediaConverter"); 133 be_locale.LoadLanguageFile(path.Path()); 134 135 #endif 136 137 BRect dummyRect(0, 0, 10, 10); 138 fMenuBar = new BMenuBar(dummyRect, "menubar"); 139 _CreateMenu(); 140 AddChild(fMenuBar); 141 142 // background 143 BRect r(frame); 144 r.OffsetTo(0, 0); 145 BView *background = new BView(r, NULL, B_FOLLOW_ALL_SIDES, 0); 146 rgb_color c = ui_color(B_PANEL_BACKGROUND_COLOR); 147 background->SetViewColor(c); 148 background->SetLowColor(c); 149 r.InsetBy(5, 25); 150 151 // file list view box 152 BRect r2(r); 153 r2.bottom = r2.top + 420; 154 r2.right = r2.left + 150; 155 fBox1 = new BBox(r2, NULL, B_FOLLOW_ALL); 156 157 BRect r3(r2); 158 r3.OffsetTo(0, 0); 159 r3.InsetBy(8, 8); 160 r3.top += be_bold_font->Size() - 3; 161 bool useHorizontalScrollBar = false; 162 if (useHorizontalScrollBar) 163 r3.bottom -= B_H_SCROLL_BAR_HEIGHT; 164 r3.right -= B_V_SCROLL_BAR_WIDTH; 165 fListView = new MediaFileListView(r3, B_FOLLOW_ALL); 166 BScrollView *scroller = new BScrollView(NULL, fListView, 167 B_FOLLOW_ALL, 0, useHorizontalScrollBar, true); 168 fBox1->AddChild(scroller); 169 background->AddChild(fBox1); 170 171 // info box 172 r2.left = r2.right + 5; 173 r2.right = r.right - 5; 174 r2.bottom = r2.top + 120; 175 fBox2 = new BBox(r2, NULL, B_FOLLOW_RIGHT | B_FOLLOW_TOP); 176 177 r3 = r2; 178 r3.OffsetTo(0, 0); 179 r3.InsetBy(5, 5); 180 r3.top += 12; 181 fInfoView = new MediaFileInfoView(r3, B_FOLLOW_ALL); 182 fBox2->AddChild(fInfoView); 183 background->AddChild(fBox2); 184 185 r2.top = r2.bottom + 5; 186 r2.bottom = r2.top + 295; 187 fBox3 = new BBox(r2, NULL, B_FOLLOW_RIGHT | B_FOLLOW_TOP_BOTTOM); 188 189 r3 = r2; 190 r3.OffsetTo(0, 0); 191 r3.InsetBy(8, 8); 192 r3.top += be_bold_font->Size() - 3; 193 194 BRect r4(r3); 195 r4.bottom = r4.top + 20; 196 BPopUpMenu* popmenu = new BPopUpMenu(""); 197 fFormatMenu = new BMenuField(r4, NULL, FORMAT_LABEL, popmenu, 198 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 199 fBox3->AddChild(fFormatMenu); 200 201 r4.top = r4.bottom + 5; 202 r4.bottom = r4.top + 20; 203 popmenu = new BPopUpMenu(""); 204 fAudioMenu = new BMenuField(r4, NULL, AUDIO_LABEL, popmenu, 205 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 206 fBox3->AddChild(fAudioMenu); 207 208 r4.top = r4.bottom + 5; 209 r4.bottom = r4.top + 20; 210 popmenu = new BPopUpMenu(""); 211 fVideoMenu = new BMenuField(r4, NULL, VIDEO_LABEL, popmenu, 212 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 213 fBox3->AddChild(fVideoMenu); 214 215 // output folder 216 r4.top = r4.bottom + 5; 217 r4.bottom = r4.top + 20; 218 r4.right = 80; 219 fDestButton = new BButton(r4, NULL, OUTPUT_FOLDER_LABEL, 220 new BMessage(OUTPUT_FOLDER_MESSAGE), 221 B_FOLLOW_LEFT | B_FOLLOW_TOP); 222 fBox3->AddChild(fDestButton); 223 fDestButton->ResizeToPreferred(); 224 BRect buttonFrame2(fDestButton->Frame()); 225 buttonFrame2.OffsetTo(r.right - buttonFrame2.Width(), 226 r.bottom - buttonFrame2.Height()); 227 228 fOutputFolder = new BStringView(r4, NULL, defaultdirectory, 229 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW); 230 fBox3->AddChild(fOutputFolder); 231 fOutputFolder->MoveBy(buttonFrame2.Width() + 10, 5); 232 fOutputFolder->ResizeToPreferred(); 233 234 // start/end duration 235 r4.top = r4.bottom + 10; 236 r4.bottom = r4.top + 20; 237 r4.right = r3.right; 238 fStartDurationTC = new BTextControl(r4, NULL, "", "0", NULL, 239 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 240 fBox3->AddChild(fStartDurationTC); 241 fStartDurationTC->SetText("0"); 242 243 r4.top = r4.bottom + 5; 244 r4.bottom = r4.top + 20; 245 fEndDurationTC = new BTextControl(r4, NULL, "", "0", NULL, 246 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 247 fBox3->AddChild(fEndDurationTC); 248 fEndDurationTC->SetText("0"); 249 250 r4.top = r4.bottom + 5; 251 r4.bottom = r4.top + 50; 252 253 // Video Quality 254 fVideoQualitySlider = new BSlider(r4, "VSlider", "" , 255 new BMessage(VIDEO_QUALITY_CHANGED_MESSAGE), 1, 100, B_HORIZONTAL, 256 B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 257 fVideoQualitySlider->SetValue(fVideoQuality); 258 fVideoQualitySlider->SetEnabled(false); 259 fBox3->AddChild(fVideoQualitySlider); 260 261 r4.top = r4.bottom + 5; 262 r4.bottom = r4.top + 50; 263 264 // Audio Quality 265 fAudioQualitySlider = new BSlider(r4,"ASlider", "" , 266 new BMessage(AUDIO_QUALITY_CHANGED_MESSAGE), 1, 100, B_HORIZONTAL, 267 B_BLOCK_THUMB, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 268 fAudioQualitySlider->SetValue(fAudioQuality); 269 fAudioQualitySlider->SetEnabled(false); 270 fBox3->AddChild(fAudioQualitySlider); 271 background->AddChild(fBox3); 272 273 // buttons 274 r2.top = r2.bottom + 15; 275 r2.bottom = r2.top + 20; 276 r2.left = r.left - 120; 277 r2.right = r.right; 278 279 fPreviewButton = new BButton(r2, NULL, PREVIEW_BUTTON_LABEL, 280 new BMessage(PREVIEW_MESSAGE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 281 background->AddChild(fPreviewButton); 282 fPreviewButton->SetEnabled(false); 283 284 fConvertButton = new BButton(r2, NULL, CONVERT_LABEL, 285 new BMessage(CONVERT_BUTTON_MESSAGE), 286 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 287 background->AddChild(fConvertButton); 288 289 // Status view 290 r2.bottom = r2.top + 20; 291 r2.left = r.left; 292 r2.right = r.right; 293 294 fStatusView2 = new StatusView(r2, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 295 background->AddChild(fStatusView2); 296 297 r2.top += 15; 298 r2.bottom += 20; 299 300 fStatusView = new StatusView(r2, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM); 301 background->AddChild(fStatusView); 302 AddChild(background); 303 304 SetStatusMessage(""); 305 _UpdateLabels(); 306 307 SetSizeLimits(frame.Width(), 32000, frame.Height(), 32000); 308 } 309 310 311 MediaConverterWindow::~MediaConverterWindow() 312 { 313 delete fSaveFilePanel; 314 delete fOpenFilePanel; 315 } 316 317 318 // #pragma mark - 319 320 321 /* 322 void 323 MediaConverterWindow::DispatchMessage(BMessage *msg, BHandler *handler) 324 { 325 if (msg->WasDropped() && msg->what == B_SIMPLE_DATA) { 326 327 printf("Dispatch 1\n"); 328 DetachCurrentMessage(); 329 msg->what = B_REFS_RECEIVED; 330 BMessenger(be_app).SendMessage(msg); 331 delete msg; 332 } else { 333 BWindow::DispatchMessage(msg, handler); 334 } 335 } 336 */ 337 338 339 void 340 MediaConverterWindow::MessageReceived(BMessage *msg) 341 { 342 status_t status; 343 entry_ref ref; 344 entry_ref inRef; 345 346 BString string, string2; 347 348 // TODO: for preview, launch the default file app instead of hardcoded MediaPlayer 349 BEntry entry("/boot/system/apps/MediaPlayer", true); 350 char buffer[40]; 351 char buffer2[B_PATH_NAME_LENGTH]; 352 char *argv[3]; 353 argv[0] = "-pos"; 354 BMediaFile *inFile(NULL); 355 int32 srcIndex = 0; 356 BPath name; 357 BEntry inentry; 358 int32 value; 359 BRect ButtonRect; 360 361 switch (msg->what) { 362 #if B_BEOS_VERSION <= B_BEOS_VERSION_6 363 case B_LANGUAGE_CHANGED: 364 LanguageChanged(); 365 break; 366 #endif 367 368 case INIT_FORMAT_MENUS: 369 BuildFormatMenu(); 370 if (CountSourceFiles() == 0) 371 SetEnabled(false, false); 372 break; 373 374 case B_SIMPLE_DATA: 375 if (msg->WasDropped()) 376 { 377 DetachCurrentMessage(); 378 msg->what = B_REFS_RECEIVED; 379 BMessenger(be_app).SendMessage(msg); 380 delete msg; 381 } 382 break; 383 384 case FORMAT_SELECT_MESSAGE: 385 BuildAudioVideoMenus(); 386 break; 387 case AUDIO_CODEC_SELECT_MESSAGE: 388 break; 389 case VIDEO_CODEC_SELECT_MESSAGE: 390 break; 391 392 case CONVERT_BUTTON_MESSAGE: 393 if (!fConverting) { 394 fConvertButton->SetLabel(CANCEL_LABEL); 395 fConverting = true; 396 SetStatusMessage(CONVERT_LABEL); 397 SetEnabled(false, true); 398 BMessenger(be_app).SendMessage(START_CONVERSION_MESSAGE); 399 } else if (!fCancelling) { 400 fCancelling = true; 401 SetStatusMessage(CANCELLING_LABEL B_UTF8_ELLIPSIS); 402 BMessenger(be_app).SendMessage(CANCEL_CONVERSION_MESSAGE); 403 } 404 break; 405 406 case CONVERSION_DONE_MESSAGE: 407 SetStatusMessage(fCancelling ? CONV_CANCEL_LABEL : CONV_COMPLETE_LABEL); 408 fConverting = false; 409 fCancelling = false; 410 { 411 bool enable = CountSourceFiles() > 0; 412 SetEnabled(enable, enable); 413 } 414 fConvertButton->SetLabel(CONVERT_LABEL); 415 416 417 break; 418 419 case OUTPUT_FOLDER_MESSAGE: 420 // Execute Save Panel 421 if (!fSaveFilePanel) { 422 BButton *SelectThisDir; 423 424 BMessage message(FOLDER_SELECT_MESSAGE); 425 fSaveFilePanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, 426 B_DIRECTORY_NODE, true, &message, NULL, false, true); 427 fSaveFilePanel->SetButtonLabel(B_DEFAULT_BUTTON, SELECT_LABEL); 428 fSaveFilePanel->Window()->SetTitle(SAVE_DIR_LABEL); 429 fSaveFilePanel->SetTarget(this); 430 431 fSaveFilePanel->Window()->Lock(); 432 ButtonRect = fSaveFilePanel->Window()->ChildAt(0)->FindView("cancel button")->Frame(); 433 ButtonRect.right = ButtonRect.left - 20; 434 ButtonRect.left = ButtonRect.right - 130; 435 SelectThisDir = new BButton(ButtonRect, NULL, SELECT_DIR_LABEL, 436 new BMessage(SELECT_THIS_DIR_MESSAGE), B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT); 437 SelectThisDir->SetTarget(this); 438 fSaveFilePanel->Window()->ChildAt(0)->AddChild(SelectThisDir); 439 fSaveFilePanel->Window()->Unlock(); 440 441 BRefFilter *filter; 442 filter = new DirectoryFilter; 443 fSaveFilePanel->SetRefFilter(filter); 444 } 445 fSaveFilePanel->Show(); 446 break; 447 448 case FOLDER_SELECT_MESSAGE: 449 // "SELECT" Button at Save Panel Pushed 450 fSaveFilePanel->GetNextSelectedRef(&inRef); 451 inentry.SetTo(&inRef, true); 452 _SetOutputFolder(inentry); 453 fOutputDirSpecified = true; 454 break; 455 456 case SELECT_THIS_DIR_MESSAGE: 457 // "THIS DIR" Button at Save Panel Pushed 458 fSaveFilePanel->GetPanelDirectory(&inRef); 459 fSaveFilePanel->Hide(); 460 inentry.SetTo(&inRef, true); 461 _SetOutputFolder(inentry); 462 fOutputDirSpecified = true; 463 break; 464 465 case OPEN_FILE_MESSAGE: 466 // Execute Open Panel 467 if (!fOpenFilePanel) { 468 fOpenFilePanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, 469 B_FILE_NODE, true, NULL, NULL, false, true); 470 fOpenFilePanel->SetTarget(this); 471 } 472 fOpenFilePanel->Show(); 473 break; 474 475 case B_REFS_RECEIVED: 476 // Media Files Seleced by Open Panel 477 DetachCurrentMessage(); 478 msg->what = B_REFS_RECEIVED; 479 BMessenger(be_app).SendMessage(msg); 480 // fall through 481 482 case B_CANCEL: 483 break; 484 485 case DISP_ABOUT_MESSAGE: { 486 (new BAlert(ABOUT_TITLE_LABEL B_UTF8_ELLIPSIS, 487 "MediaConverter\n" 488 VERSION"\n" 489 B_UTF8_COPYRIGHT" 1999, Be Incorporated.\n" 490 B_UTF8_COPYRIGHT" 2000-2004 Jun Suzuki\n" 491 B_UTF8_COPYRIGHT" 2007 Stephan Aßmus", 492 OK_LABEL))->Go(); 493 break; 494 } 495 496 case QUIT_MESSAGE: 497 MediaConverterWindow::QuitRequested(); 498 break; 499 500 case PREVIEW_MESSAGE: 501 entry.GetRef(&ref); 502 string = ""; 503 string << fStartDurationTC->Text(); 504 string << "000"; 505 506 strcpy(buffer,string.String()); 507 argv[1] = buffer; 508 srcIndex = fListView->CurrentSelection(); 509 status = GetSourceFileAt(srcIndex, &inFile, &inRef); 510 if (status == B_OK) { 511 inentry.SetTo(&inRef); 512 inentry.GetPath(&name); 513 514 strcpy(buffer, string.String()); 515 516 strcpy(buffer2, name.Path()); 517 argv[2]= buffer2; 518 } 519 520 status = be_roster->Launch(&ref, 3, argv); 521 522 if (status != B_OK) { 523 string2 << LAUNCH_ERROR << strerror(status); 524 (new BAlert("", string2.String(), OK_LABEL))->Go(); 525 } 526 break; 527 528 case VIDEO_QUALITY_CHANGED_MESSAGE: 529 msg->FindInt32("be:value",&value); 530 sprintf(buffer, VIDEO_QUALITY_LABEL, (int8)value); 531 fVideoQualitySlider->SetLabel(buffer); 532 fVideoQuality = value; 533 break; 534 535 case AUDIO_QUALITY_CHANGED_MESSAGE: 536 msg->FindInt32("be:value",&value); 537 sprintf(buffer, AUDIO_QUALITY_LABEL, (int8)value); 538 fAudioQualitySlider->SetLabel(buffer); 539 fAudioQuality = value; 540 break; 541 542 default: 543 BWindow::MessageReceived(msg); 544 } 545 } 546 547 548 bool 549 MediaConverterWindow::QuitRequested() 550 { 551 if (!fConverting) { 552 BMessenger(be_app).SendMessage(B_QUIT_REQUESTED); 553 return true; 554 } else if (!fCancelling) { 555 fCancelling = true; 556 SetStatusMessage(CANCELLING_LABEL); 557 BMessenger(be_app).SendMessage(CANCEL_CONVERSION_MESSAGE); 558 } 559 return false; 560 } 561 562 563 // #pragma mark - 564 565 566 void 567 MediaConverterWindow::LanguageChanged() 568 { 569 _DestroyMenu(); 570 _CreateMenu(); 571 _UpdateLabels(); 572 BuildAudioVideoMenus(); 573 Lock(); 574 fInfoView->Invalidate(); 575 Unlock(); 576 } 577 578 579 void 580 MediaConverterWindow::BuildAudioVideoMenus() 581 { 582 BMenu *menu = fAudioMenu->Menu(); 583 BMenuItem *item; 584 // clear out old audio codec menu items 585 while ((item = menu->RemoveItem((int32)0)) != NULL) { 586 delete item; 587 } 588 589 bool separator = true; 590 591 // get selected file format 592 FileFormatMenuItem *ffmi = (FileFormatMenuItem*)fFormatMenu->Menu()->FindMarked(); 593 media_file_format *mf_format = &(ffmi->fFileFormat); 594 595 media_format format, outfmt; 596 memset(&format, 0, sizeof(format)); 597 media_codec_info codec_info; 598 int32 cookie = 0; 599 CodecMenuItem* cmi; 600 601 // add available audio encoders to menu 602 format.type = B_MEDIA_RAW_AUDIO; 603 format.u.raw_audio = media_raw_audio_format::wildcard; 604 while (get_next_encoder(&cookie, mf_format, &format, &outfmt, &codec_info) == B_OK) { 605 if (separator) { 606 menu->AddItem(new BMenuItem("No Audio", 607 new BMessage(AUDIO_CODEC_SELECT_MESSAGE))); 608 menu->AddSeparatorItem(); 609 separator = false; 610 } 611 612 cmi = new CodecMenuItem(&codec_info, AUDIO_CODEC_SELECT_MESSAGE); 613 menu->AddItem(cmi); 614 // reset media format struct 615 /* 616 format.type = B_MEDIA_RAW_AUDIO; 617 format.u.raw_audio = media_raw_audio_format::wildcard; 618 */ 619 } 620 621 // mark first audio encoder 622 item = menu->ItemAt(0); 623 if (item != NULL) { 624 fAudioMenu->SetEnabled(fEnabled); 625 fAudioQualitySlider->SetEnabled(fEnabled); 626 item->SetMarked(true); 627 ((BInvoker *)item)->Invoke(); 628 } else { 629 item = new BMenuItem(NONE_LABEL, NULL); 630 menu->AddItem(item); 631 item->SetMarked(true); 632 fAudioMenu->SetEnabled(false); 633 fAudioQualitySlider->SetEnabled(false); 634 } 635 636 // clear out old video codec menu items 637 menu = fVideoMenu->Menu(); 638 while ((item = menu->RemoveItem((int32)0)) != NULL) { 639 delete item; 640 } 641 642 separator = true; 643 644 // construct a generic video format. Some of these parameters 645 // seem silly, but are needed for R4.5.x, which is more picky 646 // than subsequent BeOS releases will be. 647 memset(&format, 0, sizeof(format)); 648 format.type = B_MEDIA_RAW_VIDEO; 649 format.u.raw_video.last_active = (uint32)(240 - 1); 650 format.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT; 651 format.u.raw_video.display.format = B_RGB32; 652 format.u.raw_video.display.line_width = (int32)320; 653 format.u.raw_video.display.line_count = (int32)240; 654 format.u.raw_video.display.bytes_per_row = 4 * 320; 655 656 // add available video encoders to menu 657 cookie = 0; 658 while (get_next_encoder(&cookie, mf_format, &format, &outfmt, &codec_info) == B_OK) { 659 if (separator) { 660 menu->AddItem(new BMenuItem("No Video", 661 new BMessage(VIDEO_CODEC_SELECT_MESSAGE))); 662 menu->AddSeparatorItem(); 663 separator = false; 664 } 665 666 cmi = new CodecMenuItem(&codec_info, VIDEO_CODEC_SELECT_MESSAGE); 667 menu->AddItem(cmi); 668 } 669 670 // mark first video encoder 671 item = menu->ItemAt(0); 672 if (item != NULL) { 673 fVideoMenu->SetEnabled(fEnabled); 674 fVideoQualitySlider->SetEnabled(fEnabled); 675 item->SetMarked(true); 676 ((BInvoker *)item)->Invoke(); 677 } else { 678 item = new BMenuItem(NONE_LABEL, NULL); 679 menu->AddItem(item); 680 item->SetMarked(true); 681 fVideoMenu->SetEnabled(false); 682 fVideoQualitySlider->SetEnabled(false); 683 } 684 } 685 686 void 687 MediaConverterWindow::GetSelectedFormatInfo(media_file_format** format, 688 media_codec_info** audio, media_codec_info** video) 689 { 690 *audio = NULL; 691 *video = NULL; 692 *format = NULL; 693 694 FileFormatMenuItem *formatItem = 695 dynamic_cast<FileFormatMenuItem *>(fFormatMenu->Menu()->FindMarked()); 696 if (formatItem != NULL) { 697 *format = &(formatItem->fFileFormat); 698 } 699 700 *audio = *video = NULL; 701 CodecMenuItem *codecItem = 702 dynamic_cast<CodecMenuItem *>(fAudioMenu->Menu()->FindMarked()); 703 if (codecItem != NULL) { 704 *audio = &(codecItem->fCodecInfo); 705 } 706 707 codecItem = dynamic_cast<CodecMenuItem *>(fVideoMenu->Menu()->FindMarked()); 708 if (codecItem != NULL) { 709 *video = &(codecItem->fCodecInfo); 710 } 711 } 712 713 714 void 715 MediaConverterWindow::BuildFormatMenu() 716 { 717 BMenu *menu = fFormatMenu->Menu(); 718 BMenuItem *item; 719 // clear out old format menu items 720 while ((item = menu->RemoveItem((int32)0)) != NULL) { 721 delete item; 722 } 723 724 // add menu items for each file format 725 media_file_format mfi; 726 int32 cookie = 0; 727 FileFormatMenuItem *ff_item; 728 while (get_next_file_format(&cookie, &mfi) == B_OK) { 729 ff_item = new FileFormatMenuItem(&mfi); 730 menu->AddItem(ff_item); 731 } 732 733 // mark first item 734 item = menu->ItemAt(0); 735 if (item != NULL) { 736 item->SetMarked(true); 737 ((BInvoker *)item)->Invoke(); 738 } 739 } 740 741 void 742 MediaConverterWindow::SetFileMessage(const char *message) 743 { 744 fStatusView->SetStatus(message); 745 } 746 747 void 748 MediaConverterWindow::SetStatusMessage(const char *message) 749 { 750 fStatusView2->SetStatus(message); 751 } 752 753 754 // #pragma mark - 755 756 757 void 758 MediaConverterWindow::AddSourceFile(BMediaFile* file, const entry_ref& ref) 759 { 760 fListView->AddItem(file, ref); 761 762 if (!fOutputDirSpecified) { 763 BEntry entry(&ref); 764 entry.GetParent(&entry); 765 _SetOutputFolder(entry); 766 } 767 } 768 769 770 void 771 MediaConverterWindow::RemoveSourceFile(int32 index) 772 { 773 delete fListView->RemoveItem(index); 774 fStartDurationTC->SetText("0"); 775 fEndDurationTC->SetText("0"); 776 } 777 778 779 int32 780 MediaConverterWindow::CountSourceFiles() 781 { 782 return fListView->CountItems(); 783 } 784 785 786 status_t 787 MediaConverterWindow::GetSourceFileAt(int32 index, BMediaFile** _file, 788 entry_ref* ref) 789 { 790 MediaFileListItem* item = dynamic_cast<MediaFileListItem*>( 791 fListView->ItemAt(index)); 792 if (item != NULL) { 793 *_file = item->fMediaFile; 794 *ref = item->fRef; 795 return B_OK; 796 } else { 797 return B_ERROR; 798 } 799 } 800 801 802 void 803 MediaConverterWindow::SourceFileSelectionChanged() 804 { 805 int32 selected = fListView->CurrentSelection(); 806 BMediaFile* file = NULL; 807 entry_ref* _ref = NULL; 808 entry_ref ref; 809 bool enabled = false; 810 if (GetSourceFileAt(selected, &file, &ref) == B_OK) { 811 _ref = &ref; 812 enabled = true; 813 } 814 815 fPreviewButton->SetEnabled(enabled); 816 fVideoQualitySlider->SetEnabled(enabled); 817 fAudioQualitySlider->SetEnabled(enabled); 818 fStartDurationTC->SetEnabled(enabled); 819 fEndDurationTC->SetEnabled(enabled); 820 821 fInfoView->Update(file, _ref); 822 823 // HACK: get the fInfoView to update the duration "synchronously" 824 UpdateIfNeeded(); 825 826 // update duration text controls 827 fStartDurationTC->SetText("0"); 828 BString duration; 829 duration << fInfoView->Duration() / 1000; 830 fEndDurationTC->SetText(duration.String()); 831 } 832 833 834 // #pragma mark - 835 836 837 void 838 MediaConverterWindow::SetEnabled(bool enabled, bool convertEnabled) 839 { 840 fConvertButton->SetEnabled(convertEnabled); 841 if (enabled == fEnabled) 842 return; 843 844 fFormatMenu->SetEnabled(enabled); 845 fAudioMenu->SetEnabled(enabled); 846 fVideoMenu->SetEnabled(enabled); 847 fListView->SetEnabled(enabled); 848 fStartDurationTC->SetEnabled(enabled); 849 fEndDurationTC->SetEnabled(enabled); 850 851 fEnabled = enabled; 852 } 853 854 855 bool 856 MediaConverterWindow::IsEnabled() 857 { 858 return fEnabled; 859 } 860 861 862 const char* 863 MediaConverterWindow::StartDuration() const 864 { 865 return fStartDurationTC->Text(); 866 } 867 868 869 const char* 870 MediaConverterWindow::EndDuration() const 871 { 872 return fEndDurationTC->Text(); 873 } 874 875 876 BDirectory 877 MediaConverterWindow::OutputDirectory() const 878 { 879 return fOutputDir; 880 } 881 882 883 void 884 MediaConverterWindow::SetAudioQualityLabel(const char* label) 885 { 886 fAudioQualitySlider->SetLabel(label); 887 } 888 889 890 void 891 MediaConverterWindow::SetVideoQualityLabel(const char* label) 892 { 893 fVideoQualitySlider->SetLabel(label); 894 } 895 896 897 // #pragma mark - 898 899 900 void 901 MediaConverterWindow::_UpdateLabels() 902 { 903 char buffer[255]; 904 905 if (fBox1 != NULL) 906 fBox1->SetLabel(SOURCE_BOX_LABEL); 907 if (fBox2 != NULL) 908 fBox2->SetLabel(INFO_BOX_LABEL); 909 if (fBox3 != NULL) 910 fBox3->SetLabel(OUTPUT_BOX_LABEL); 911 912 BRect r(Bounds()); 913 float w = 0; 914 915 if (fConvertButton != NULL) { 916 fConvertButton->SetLabel(CONVERT_LABEL); 917 fConvertButton->ResizeToPreferred(); 918 BRect buttonFrame(fConvertButton->Frame()); 919 w = buttonFrame.Width(); 920 buttonFrame.OffsetTo(r.right - w - 10, r.bottom - buttonFrame.Height() - 25); 921 fConvertButton->MoveTo(buttonFrame.LeftTop()); 922 } 923 924 if (fPreviewButton != NULL) { 925 fPreviewButton->SetLabel(PREVIEW_BUTTON_LABEL); 926 fPreviewButton->ResizeToPreferred(); 927 BRect buttonFrame(fPreviewButton->Frame()); 928 w = buttonFrame.Width(); 929 buttonFrame.OffsetTo(r.right - w - buttonFrame.Width() - 40, 930 r.bottom - buttonFrame.Height() - 25); 931 fPreviewButton->MoveTo(buttonFrame.LeftTop()); 932 } 933 934 if (fDestButton != NULL) { 935 fDestButton->SetLabel(OUTPUT_FOLDER_LABEL); 936 fDestButton->ResizeToPreferred(); 937 } 938 939 if (fOutputFolder != NULL) { 940 BRect destrect; 941 destrect = fDestButton->Frame(); 942 fOutputFolder->MoveTo(destrect.right + 10, destrect.top + 5); 943 fOutputFolder->ResizeToPreferred(); 944 } 945 946 sprintf(buffer, VIDEO_QUALITY_LABEL, (int8)fVideoQuality); 947 if (fVideoQualitySlider != NULL) { 948 fVideoQualitySlider->SetLabel(buffer); 949 fVideoQualitySlider->SetLimitLabels(SLIDER_LOW_LABEL, 950 SLIDER_HIGH_LABEL); 951 } 952 953 sprintf(buffer, AUDIO_QUALITY_LABEL, (int8)fAudioQuality); 954 955 if (fAudioQualitySlider != NULL) { 956 fAudioQualitySlider->SetLabel(buffer); 957 fAudioQualitySlider->SetLimitLabels(SLIDER_LOW_LABEL, 958 SLIDER_HIGH_LABEL); 959 } 960 961 float maxLabelLen = 0; 962 if (fStartDurationTC != NULL) { 963 fStartDurationTC->SetLabel(START_LABEL); 964 maxLabelLen = fStartDurationTC->StringWidth(START_LABEL); 965 } 966 if (fEndDurationTC != NULL) { 967 fEndDurationTC->SetLabel(END_LABEL); 968 maxLabelLen = MAX(maxLabelLen, fEndDurationTC->StringWidth(END_LABEL)); 969 } 970 if (fStartDurationTC != NULL) 971 fStartDurationTC->SetDivider(maxLabelLen + 5); 972 if (fEndDurationTC != NULL) 973 fEndDurationTC->SetDivider(maxLabelLen + 5); 974 975 if (fFormatMenu != NULL) { 976 fFormatMenu->SetLabel(FORMAT_LABEL); 977 maxLabelLen = MAX(maxLabelLen, fFormatMenu->StringWidth( 978 fFormatMenu->Label())); 979 } 980 if (fAudioMenu != NULL) { 981 fAudioMenu->SetLabel(AUDIO_LABEL); 982 maxLabelLen = MAX(maxLabelLen, fAudioMenu->StringWidth( 983 fAudioMenu->Label())); 984 } 985 if (fVideoMenu != NULL) { 986 fVideoMenu->SetLabel(VIDEO_LABEL); 987 maxLabelLen = MAX(maxLabelLen, fVideoMenu->StringWidth( 988 fVideoMenu->Label())); 989 } 990 maxLabelLen += 10; 991 992 if (fStartDurationTC != NULL) 993 fStartDurationTC->SetDivider(maxLabelLen); 994 if (fEndDurationTC != NULL) 995 fEndDurationTC->SetDivider(maxLabelLen); 996 if (fFormatMenu != NULL) 997 fFormatMenu->SetDivider(maxLabelLen + 3); 998 if (fAudioMenu != NULL) 999 fAudioMenu->SetDivider(maxLabelLen + 3); 1000 if (fVideoMenu != NULL) 1001 fVideoMenu->SetDivider(maxLabelLen + 3); 1002 1003 SetFileMessage(DROP_MEDIA_FILE_LABEL); 1004 } 1005 1006 1007 void 1008 MediaConverterWindow::_DestroyMenu() 1009 { 1010 BMenu* Menu; 1011 1012 while ((Menu = fMenuBar->SubmenuAt(0)) != NULL) { 1013 fMenuBar->RemoveItem(Menu); 1014 delete Menu; 1015 } 1016 } 1017 1018 1019 void 1020 MediaConverterWindow::_CreateMenu() 1021 { 1022 BMenuItem* item; 1023 BMenu* menu; 1024 1025 menu = new BMenu(FILE_MENU_LABEL); 1026 item = new BMenuItem(OPEN_MENU_LABEL B_UTF8_ELLIPSIS, 1027 new BMessage(OPEN_FILE_MESSAGE)); 1028 menu->AddItem(item); 1029 menu->AddSeparatorItem(); 1030 item = new BMenuItem(ABOUT_MENU_LABEL B_UTF8_ELLIPSIS, 1031 new BMessage(DISP_ABOUT_MESSAGE)); 1032 menu->AddItem(item); 1033 menu->AddSeparatorItem(); 1034 item = new BMenuItem(QUIT_MENU_LABEL, new BMessage(QUIT_MESSAGE)); 1035 menu->AddItem(item); 1036 1037 fMenuBar->AddItem(menu); 1038 } 1039 1040 1041 void 1042 MediaConverterWindow::_SetOutputFolder(BEntry entry) 1043 { 1044 BPath path; 1045 entry.GetPath(&path); 1046 fOutputFolder->SetText(path.Path()); 1047 fOutputFolder->ResizeToPreferred(); 1048 fOutputDir.SetTo(path.Path()); 1049 } 1050 1051 1052