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 } 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 BEntry entry("/boot/beos/apps/MediaPlayer", true); 347 char buffer[40]; 348 char buffer2[B_PATH_NAME_LENGTH]; 349 char *argv[3]; 350 argv[0] = "-pos"; 351 BMediaFile *inFile(NULL); 352 int32 srcIndex = 0; 353 BPath name; 354 BEntry inentry; 355 int32 value; 356 BRect ButtonRect; 357 358 switch (msg->what) { 359 #if B_BEOS_VERSION <= B_BEOS_VERSION_6 360 case B_LANGUAGE_CHANGED: 361 LanguageChanged(); 362 break; 363 #endif 364 365 case INIT_FORMAT_MENUS: 366 BuildFormatMenu(); 367 if (CountSourceFiles() == 0) 368 SetEnabled(false, false); 369 break; 370 371 case B_SIMPLE_DATA: 372 if (msg->WasDropped()) 373 { 374 DetachCurrentMessage(); 375 msg->what = B_REFS_RECEIVED; 376 BMessenger(be_app).SendMessage(msg); 377 delete msg; 378 } 379 break; 380 381 case FORMAT_SELECT_MESSAGE: 382 BuildAudioVideoMenus(); 383 break; 384 case AUDIO_CODEC_SELECT_MESSAGE: 385 break; 386 case VIDEO_CODEC_SELECT_MESSAGE: 387 break; 388 389 case CONVERT_BUTTON_MESSAGE: 390 if (!fConverting) { 391 fConvertButton->SetLabel(CANCEL_LABEL); 392 fConverting = true; 393 SetStatusMessage(CONVERT_LABEL); 394 SetEnabled(false, true); 395 BMessenger(be_app).SendMessage(START_CONVERSION_MESSAGE); 396 } else if (!fCancelling) { 397 fCancelling = true; 398 SetStatusMessage(CANCELLING_LABEL B_UTF8_ELLIPSIS); 399 BMessenger(be_app).SendMessage(CANCEL_CONVERSION_MESSAGE); 400 } 401 break; 402 403 case CONVERSION_DONE_MESSAGE: 404 SetStatusMessage(fCancelling ? CONV_CANCEL_LABEL : CONV_COMPLETE_LABEL); 405 fConverting = false; 406 fCancelling = false; 407 { 408 bool enable = CountSourceFiles() > 0; 409 SetEnabled(enable, enable); 410 } 411 fConvertButton->SetLabel(CONVERT_LABEL); 412 413 414 break; 415 416 case OUTPUT_FOLDER_MESSAGE: 417 // Execute Save Panel 418 if (!fSaveFilePanel) { 419 BButton *SelectThisDir; 420 421 fSaveFilePanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, B_DIRECTORY_NODE, true, new BMessage(FOLDER_SELECT_MESSAGE), NULL, false, true); 422 fSaveFilePanel->SetButtonLabel(B_DEFAULT_BUTTON, SELECT_LABEL); 423 fSaveFilePanel->Window()->SetTitle(SAVE_DIR_LABEL); 424 fSaveFilePanel->SetTarget(this); 425 426 fSaveFilePanel->Window()->Lock(); 427 ButtonRect = fSaveFilePanel->Window()->ChildAt(0)->FindView("cancel button")->Frame(); 428 ButtonRect.right = ButtonRect.left - 20; 429 ButtonRect.left = ButtonRect.right - 130; 430 SelectThisDir = new BButton(ButtonRect, NULL, SELECT_DIR_LABEL, 431 new BMessage(SELECT_THIS_DIR_MESSAGE), B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT); 432 SelectThisDir->SetTarget(this); 433 fSaveFilePanel->Window()->ChildAt(0)->AddChild(SelectThisDir); 434 fSaveFilePanel->Window()->Unlock(); 435 436 BRefFilter *filter; 437 filter = new DirectoryFilter; 438 fSaveFilePanel->SetRefFilter(filter); 439 } 440 fSaveFilePanel->Show(); 441 break; 442 443 case FOLDER_SELECT_MESSAGE: 444 // "SELECT" Button at Save Panel Pushed 445 fSaveFilePanel->GetNextSelectedRef(&inRef); 446 inentry.SetTo(&inRef, true); 447 _SetOutputFolder(inentry); 448 fOutputDirSpecified = true; 449 break; 450 451 case SELECT_THIS_DIR_MESSAGE: 452 // "THIS DIR" Button at Save Panel Pushed 453 fSaveFilePanel->GetPanelDirectory(&inRef); 454 fSaveFilePanel->Hide(); 455 inentry.SetTo(&inRef, true); 456 _SetOutputFolder(inentry); 457 fOutputDirSpecified = true; 458 break; 459 460 case OPEN_FILE_MESSAGE: 461 // Execute Open Panel 462 if (!fOpenFilePanel) { 463 fOpenFilePanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, B_FILE_NODE, true, NULL, NULL, false, true); 464 fOpenFilePanel->SetTarget(this); 465 } 466 fOpenFilePanel->Show(); 467 break; 468 469 case B_REFS_RECEIVED: 470 // Media Files Seleced by Open Panel 471 DetachCurrentMessage(); 472 msg->what = B_REFS_RECEIVED; 473 BMessenger(be_app).SendMessage(msg); 474 // fall through 475 476 case B_CANCEL: 477 break; 478 479 case DISP_ABOUT_MESSAGE: { 480 (new BAlert(ABOUT_TITLE_LABEL B_UTF8_ELLIPSIS, 481 "MediaConverter\n" 482 VERSION"\n" 483 B_UTF8_COPYRIGHT" 1999, Be Incorporated.\n" 484 B_UTF8_COPYRIGHT" 2000-2004 Jun Suzuki\n" 485 B_UTF8_COPYRIGHT" 2007 Stephan Aßmus", 486 OK_LABEL))->Go(); 487 break; 488 } 489 490 case QUIT_MESSAGE: 491 MediaConverterWindow::QuitRequested(); 492 break; 493 494 case PREVIEW_MESSAGE: 495 entry.GetRef(&ref); 496 string = ""; 497 string << fStartDurationTC->Text(); 498 string << "000"; 499 500 strcpy(buffer,string.String()); 501 argv[1] = buffer; 502 srcIndex = fListView->CurrentSelection(); 503 status = GetSourceFileAt(srcIndex, &inFile, &inRef); 504 if (status == B_OK) { 505 inentry.SetTo(&inRef); 506 inentry.GetPath(&name); 507 508 strcpy(buffer, string.String()); 509 510 strcpy(buffer2, name.Path()); 511 argv[2]= buffer2; 512 } 513 514 status = be_roster->Launch(&ref, 3, argv); 515 516 if (status != B_OK) { 517 string2 << LAUNCH_ERROR << strerror(status); 518 (new BAlert("", string2.String(), OK_LABEL))->Go(); 519 } 520 break; 521 522 case VIDEO_QUALITY_CHANGED_MESSAGE: 523 msg->FindInt32("be:value",&value); 524 sprintf(buffer, VIDEO_QUALITY_LABEL, (int8)value); 525 fVideoQualitySlider->SetLabel(buffer); 526 fVideoQuality = value; 527 break; 528 529 case AUDIO_QUALITY_CHANGED_MESSAGE: 530 msg->FindInt32("be:value",&value); 531 sprintf(buffer, AUDIO_QUALITY_LABEL, (int8)value); 532 fAudioQualitySlider->SetLabel(buffer); 533 fAudioQuality = value; 534 break; 535 536 default: 537 BWindow::MessageReceived(msg); 538 } 539 } 540 541 542 bool 543 MediaConverterWindow::QuitRequested() 544 { 545 if (!fConverting) { 546 BMessenger(be_app).SendMessage(B_QUIT_REQUESTED); 547 return true; 548 } else if (!fCancelling) { 549 fCancelling = true; 550 SetStatusMessage(CANCELLING_LABEL); 551 BMessenger(be_app).SendMessage(CANCEL_CONVERSION_MESSAGE); 552 } 553 return false; 554 } 555 556 557 // #pragma mark - 558 559 560 void 561 MediaConverterWindow::LanguageChanged() 562 { 563 _DestroyMenu(); 564 _CreateMenu(); 565 _UpdateLabels(); 566 BuildAudioVideoMenus(); 567 Lock(); 568 fInfoView->Invalidate(); 569 Unlock(); 570 } 571 572 573 void 574 MediaConverterWindow::BuildAudioVideoMenus() 575 { 576 BMenu *menu = fAudioMenu->Menu(); 577 BMenuItem *item; 578 // clear out old audio codec menu items 579 while ((item = menu->RemoveItem((int32)0)) != NULL) { 580 delete item; 581 } 582 583 bool separator = true; 584 585 // get selected file format 586 FileFormatMenuItem *ffmi = (FileFormatMenuItem*)fFormatMenu->Menu()->FindMarked(); 587 media_file_format *mf_format = &(ffmi->fFileFormat); 588 589 media_format format, outfmt; 590 memset(&format, 0, sizeof(format)); 591 media_codec_info codec_info; 592 int32 cookie = 0; 593 CodecMenuItem* cmi; 594 595 // add available audio encoders to menu 596 format.type = B_MEDIA_RAW_AUDIO; 597 format.u.raw_audio = media_raw_audio_format::wildcard; 598 while (get_next_encoder(&cookie, mf_format, &format, &outfmt, &codec_info) == B_OK) { 599 if (separator) { 600 menu->AddItem(new BMenuItem("No Audio", 601 new BMessage(AUDIO_CODEC_SELECT_MESSAGE))); 602 menu->AddSeparatorItem(); 603 separator = false; 604 } 605 606 cmi = new CodecMenuItem(&codec_info, AUDIO_CODEC_SELECT_MESSAGE); 607 menu->AddItem(cmi); 608 // reset media format struct 609 /* 610 format.type = B_MEDIA_RAW_AUDIO; 611 format.u.raw_audio = media_raw_audio_format::wildcard; 612 */ 613 } 614 615 // mark first audio encoder 616 item = menu->ItemAt(0); 617 if (item != NULL) { 618 fAudioMenu->SetEnabled(fEnabled); 619 fAudioQualitySlider->SetEnabled(fEnabled); 620 item->SetMarked(true); 621 ((BInvoker *)item)->Invoke(); 622 } else { 623 item = new BMenuItem(NONE_LABEL, NULL); 624 menu->AddItem(item); 625 item->SetMarked(true); 626 fAudioMenu->SetEnabled(false); 627 fAudioQualitySlider->SetEnabled(false); 628 } 629 630 // clear out old video codec menu items 631 menu = fVideoMenu->Menu(); 632 while ((item = menu->RemoveItem((int32)0)) != NULL) { 633 delete item; 634 } 635 636 separator = true; 637 638 // construct a generic video format. Some of these parameters 639 // seem silly, but are needed for R4.5.x, which is more picky 640 // than subsequent BeOS releases will be. 641 memset(&format, 0, sizeof(format)); 642 format.type = B_MEDIA_RAW_VIDEO; 643 format.u.raw_video.last_active = (uint32)(240 - 1); 644 format.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT; 645 format.u.raw_video.display.format = B_RGB32; 646 format.u.raw_video.display.line_width = (int32)320; 647 format.u.raw_video.display.line_count = (int32)240; 648 format.u.raw_video.display.bytes_per_row = 4 * 320; 649 650 // add available video encoders to menu 651 cookie = 0; 652 while (get_next_encoder(&cookie, mf_format, &format, &outfmt, &codec_info) == B_OK) { 653 if (separator) { 654 menu->AddItem(new BMenuItem("No Video", 655 new BMessage(VIDEO_CODEC_SELECT_MESSAGE))); 656 menu->AddSeparatorItem(); 657 separator = false; 658 } 659 660 cmi = new CodecMenuItem(&codec_info, VIDEO_CODEC_SELECT_MESSAGE); 661 menu->AddItem(cmi); 662 } 663 664 // mark first video encoder 665 item = menu->ItemAt(0); 666 if (item != NULL) { 667 fVideoMenu->SetEnabled(fEnabled); 668 fVideoQualitySlider->SetEnabled(fEnabled); 669 item->SetMarked(true); 670 ((BInvoker *)item)->Invoke(); 671 } else { 672 item = new BMenuItem(NONE_LABEL, NULL); 673 menu->AddItem(item); 674 item->SetMarked(true); 675 fVideoMenu->SetEnabled(false); 676 fVideoQualitySlider->SetEnabled(false); 677 } 678 } 679 680 void 681 MediaConverterWindow::GetSelectedFormatInfo(media_file_format** format, 682 media_codec_info** audio, media_codec_info** video) 683 { 684 *audio = NULL; 685 *video = NULL; 686 *format = NULL; 687 688 FileFormatMenuItem *formatItem = 689 dynamic_cast<FileFormatMenuItem *>(fFormatMenu->Menu()->FindMarked()); 690 if (formatItem != NULL) { 691 *format = &(formatItem->fFileFormat); 692 } 693 694 *audio = *video = NULL; 695 CodecMenuItem *codecItem = 696 dynamic_cast<CodecMenuItem *>(fAudioMenu->Menu()->FindMarked()); 697 if (codecItem != NULL) { 698 *audio = &(codecItem->fCodecInfo); 699 } 700 701 codecItem = dynamic_cast<CodecMenuItem *>(fVideoMenu->Menu()->FindMarked()); 702 if (codecItem != NULL) { 703 *video = &(codecItem->fCodecInfo); 704 } 705 } 706 707 708 void 709 MediaConverterWindow::BuildFormatMenu() 710 { 711 BMenu *menu = fFormatMenu->Menu(); 712 BMenuItem *item; 713 // clear out old format menu items 714 while ((item = menu->RemoveItem((int32)0)) != NULL) { 715 delete item; 716 } 717 718 // add menu items for each file format 719 media_file_format mfi; 720 int32 cookie = 0; 721 FileFormatMenuItem *ff_item; 722 while (get_next_file_format(&cookie, &mfi) == B_OK) { 723 ff_item = new FileFormatMenuItem(&mfi); 724 menu->AddItem(ff_item); 725 } 726 727 // mark first item 728 item = menu->ItemAt(0); 729 if (item != NULL) { 730 item->SetMarked(true); 731 ((BInvoker *)item)->Invoke(); 732 } 733 } 734 735 void 736 MediaConverterWindow::SetFileMessage(const char *message) 737 { 738 fStatusView->SetStatus(message); 739 } 740 741 void 742 MediaConverterWindow::SetStatusMessage(const char *message) 743 { 744 fStatusView2->SetStatus(message); 745 } 746 747 748 // #pragma mark - 749 750 751 void 752 MediaConverterWindow::AddSourceFile(BMediaFile* file, const entry_ref& ref) 753 { 754 fListView->AddItem(file, ref); 755 756 if (!fOutputDirSpecified) { 757 BEntry entry(&ref); 758 entry.GetParent(&entry); 759 _SetOutputFolder(entry); 760 } 761 } 762 763 764 void 765 MediaConverterWindow::RemoveSourceFile(int32 index) 766 { 767 delete fListView->RemoveItem(index); 768 fStartDurationTC->SetText("0"); 769 fEndDurationTC->SetText("0"); 770 } 771 772 773 int32 774 MediaConverterWindow::CountSourceFiles() 775 { 776 return fListView->CountItems(); 777 } 778 779 780 status_t 781 MediaConverterWindow::GetSourceFileAt(int32 index, BMediaFile** _file, 782 entry_ref* ref) 783 { 784 MediaFileListItem* item = dynamic_cast<MediaFileListItem*>( 785 fListView->ItemAt(index)); 786 if (item != NULL) { 787 *_file = item->fMediaFile; 788 *ref = item->fRef; 789 return B_OK; 790 } else { 791 return B_ERROR; 792 } 793 } 794 795 796 void 797 MediaConverterWindow::SourceFileSelectionChanged() 798 { 799 int32 selected = fListView->CurrentSelection(); 800 BMediaFile* file = NULL; 801 entry_ref* _ref = NULL; 802 entry_ref ref; 803 bool enabled = false; 804 if (GetSourceFileAt(selected, &file, &ref) == B_OK) { 805 _ref = &ref; 806 enabled = true; 807 } 808 809 fPreviewButton->SetEnabled(enabled); 810 fVideoQualitySlider->SetEnabled(enabled); 811 fAudioQualitySlider->SetEnabled(enabled); 812 fStartDurationTC->SetEnabled(enabled); 813 fEndDurationTC->SetEnabled(enabled); 814 815 fInfoView->Update(file, _ref); 816 817 // HACK: get the fInfoView to update the duration "synchronously" 818 UpdateIfNeeded(); 819 820 // update duration text controls 821 fStartDurationTC->SetText("0"); 822 BString duration; 823 duration << fInfoView->Duration() / 1000; 824 fEndDurationTC->SetText(duration.String()); 825 } 826 827 828 // #pragma mark - 829 830 831 void 832 MediaConverterWindow::SetEnabled(bool enabled, bool convertEnabled) 833 { 834 fConvertButton->SetEnabled(convertEnabled); 835 if (enabled == fEnabled) 836 return; 837 838 fFormatMenu->SetEnabled(enabled); 839 fAudioMenu->SetEnabled(enabled); 840 fVideoMenu->SetEnabled(enabled); 841 fListView->SetEnabled(enabled); 842 fStartDurationTC->SetEnabled(enabled); 843 fEndDurationTC->SetEnabled(enabled); 844 845 fEnabled = enabled; 846 } 847 848 849 bool 850 MediaConverterWindow::IsEnabled() 851 { 852 return fEnabled; 853 } 854 855 856 const char* 857 MediaConverterWindow::StartDuration() const 858 { 859 return fStartDurationTC->Text(); 860 } 861 862 863 const char* 864 MediaConverterWindow::EndDuration() const 865 { 866 return fEndDurationTC->Text(); 867 } 868 869 870 BDirectory 871 MediaConverterWindow::OutputDirectory() const 872 { 873 return fOutputDir; 874 } 875 876 877 void 878 MediaConverterWindow::SetAudioQualityLabel(const char* label) 879 { 880 fAudioQualitySlider->SetLabel(label); 881 } 882 883 884 void 885 MediaConverterWindow::SetVideoQualityLabel(const char* label) 886 { 887 fVideoQualitySlider->SetLabel(label); 888 } 889 890 891 // #pragma mark - 892 893 894 void 895 MediaConverterWindow::_UpdateLabels() 896 { 897 char buffer[255]; 898 899 if (fBox1 != NULL) 900 fBox1->SetLabel(SOURCE_BOX_LABEL); 901 if (fBox2 != NULL) 902 fBox2->SetLabel(INFO_BOX_LABEL); 903 if (fBox3 != NULL) 904 fBox3->SetLabel(OUTPUT_BOX_LABEL); 905 906 BRect r(Bounds()); 907 float w = 0; 908 909 if (fConvertButton != NULL) { 910 fConvertButton->SetLabel(CONVERT_LABEL); 911 fConvertButton->ResizeToPreferred(); 912 BRect buttonFrame(fConvertButton->Frame()); 913 w = buttonFrame.Width(); 914 buttonFrame.OffsetTo(r.right - w - 10, r.bottom - buttonFrame.Height() - 25); 915 fConvertButton->MoveTo(buttonFrame.LeftTop()); 916 } 917 918 if (fPreviewButton != NULL) { 919 fPreviewButton->SetLabel(PREVIEW_BUTTON_LABEL); 920 fPreviewButton->ResizeToPreferred(); 921 BRect buttonFrame(fPreviewButton->Frame()); 922 w = buttonFrame.Width(); 923 buttonFrame.OffsetTo(r.right - w - buttonFrame.Width() - 40, 924 r.bottom - buttonFrame.Height() - 25); 925 fPreviewButton->MoveTo(buttonFrame.LeftTop()); 926 } 927 928 if (fDestButton != NULL) { 929 fDestButton->SetLabel(OUTPUT_FOLDER_LABEL); 930 fDestButton->ResizeToPreferred(); 931 } 932 933 if (fOutputFolder != NULL) { 934 BRect destrect; 935 destrect = fDestButton->Frame(); 936 fOutputFolder->MoveTo(destrect.right + 10, destrect.top + 5); 937 fOutputFolder->ResizeToPreferred(); 938 } 939 940 sprintf(buffer, VIDEO_QUALITY_LABEL, (int8)fVideoQuality); 941 if (fVideoQualitySlider != NULL) { 942 fVideoQualitySlider->SetLabel(buffer); 943 fVideoQualitySlider->SetLimitLabels(SLIDER_LOW_LABEL, 944 SLIDER_HIGH_LABEL); 945 } 946 947 sprintf(buffer, AUDIO_QUALITY_LABEL, (int8)fAudioQuality); 948 949 if (fAudioQualitySlider != NULL) { 950 fAudioQualitySlider->SetLabel(buffer); 951 fAudioQualitySlider->SetLimitLabels(SLIDER_LOW_LABEL, 952 SLIDER_HIGH_LABEL); 953 } 954 955 float maxLabelLen = 0; 956 if (fStartDurationTC != NULL) { 957 fStartDurationTC->SetLabel(START_LABEL); 958 maxLabelLen = fStartDurationTC->StringWidth(START_LABEL); 959 } 960 if (fEndDurationTC != NULL) { 961 fEndDurationTC->SetLabel(END_LABEL); 962 maxLabelLen = MAX(maxLabelLen, fEndDurationTC->StringWidth(END_LABEL)); 963 } 964 if (fStartDurationTC != NULL) 965 fStartDurationTC->SetDivider(maxLabelLen + 5); 966 if (fEndDurationTC != NULL) 967 fEndDurationTC->SetDivider(maxLabelLen + 5); 968 969 if (fFormatMenu != NULL) { 970 fFormatMenu->SetLabel(FORMAT_LABEL); 971 maxLabelLen = MAX(maxLabelLen, fFormatMenu->StringWidth( 972 fFormatMenu->Label())); 973 } 974 if (fAudioMenu != NULL) { 975 fAudioMenu->SetLabel(AUDIO_LABEL); 976 maxLabelLen = MAX(maxLabelLen, fAudioMenu->StringWidth( 977 fAudioMenu->Label())); 978 } 979 if (fVideoMenu != NULL) { 980 fVideoMenu->SetLabel(VIDEO_LABEL); 981 maxLabelLen = MAX(maxLabelLen, fVideoMenu->StringWidth( 982 fVideoMenu->Label())); 983 } 984 maxLabelLen += 10; 985 986 if (fStartDurationTC != NULL) 987 fStartDurationTC->SetDivider(maxLabelLen); 988 if (fEndDurationTC != NULL) 989 fEndDurationTC->SetDivider(maxLabelLen); 990 if (fFormatMenu != NULL) 991 fFormatMenu->SetDivider(maxLabelLen + 3); 992 if (fAudioMenu != NULL) 993 fAudioMenu->SetDivider(maxLabelLen + 3); 994 if (fVideoMenu != NULL) 995 fVideoMenu->SetDivider(maxLabelLen + 3); 996 997 SetFileMessage(DROP_MEDIA_FILE_LABEL); 998 } 999 1000 1001 void 1002 MediaConverterWindow::_DestroyMenu() 1003 { 1004 BMenu* Menu; 1005 1006 while ((Menu = fMenuBar->SubmenuAt(0)) != NULL) { 1007 fMenuBar->RemoveItem(Menu); 1008 delete Menu; 1009 } 1010 } 1011 1012 1013 void 1014 MediaConverterWindow::_CreateMenu() 1015 { 1016 BMenuItem* item; 1017 BMenu* menu; 1018 1019 menu = new BMenu(FILE_MENU_LABEL); 1020 item = new BMenuItem(OPEN_MENU_LABEL B_UTF8_ELLIPSIS, 1021 new BMessage(OPEN_FILE_MESSAGE)); 1022 menu->AddItem(item); 1023 menu->AddSeparatorItem(); 1024 item = new BMenuItem(ABOUT_MENU_LABEL B_UTF8_ELLIPSIS, 1025 new BMessage(DISP_ABOUT_MESSAGE)); 1026 menu->AddItem(item); 1027 menu->AddSeparatorItem(); 1028 item = new BMenuItem(QUIT_MENU_LABEL, new BMessage(QUIT_MESSAGE)); 1029 menu->AddItem(item); 1030 1031 fMenuBar->AddItem(menu); 1032 } 1033 1034 1035 void 1036 MediaConverterWindow::_SetOutputFolder(BEntry entry) 1037 { 1038 BPath path; 1039 entry.GetPath(&path); 1040 fOutputFolder->SetText(path.Path()); 1041 fOutputFolder->ResizeToPreferred(); 1042 fOutputDir.SetTo(path.Path()); 1043 } 1044 1045 1046