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