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