1 // Copyright 1999, Be Incorporated. All Rights Reserved.
2 // Copyright 2000-2004, Jun Suzuki. All Rights Reserved.
3 // Copyright 2007, 2010 Stephan Aßmus. All Rights Reserved.
4 // Copyright 2010-2013, Haiku, Inc. All Rights Reserved.
5 // This file may be used under the terms of the Be Sample Code License.
8 #include "MediaConverterWindow.h"
15 #include <Application.h>
19 #include <ControlLook.h>
20 #include <FilePanel.h>
21 #include <FindDirectory.h>
22 #include <LayoutBuilder.h>
26 #include <MenuField.h>
29 #include <PopUpMenu.h>
31 #include <ScrollBar.h>
32 #include <ScrollView.h>
34 #include <StringView.h>
35 #include <TextControl.h>
37 #include "MediaFileInfoView.h"
38 #include "MediaFileListView.h"
39 #include "MessageConstants.h"
42 #undef B_TRANSLATION_CONTEXT
43 #define B_TRANSLATION_CONTEXT "MediaConverter"
44 #define VERSION "1.3.0"
47 static const unsigned int kMinSourceWidth
= 12;
48 static const unsigned int kQualitySliderWidth
= 28;
49 static const unsigned int kDurationWidth
= 10;
52 // #pragma mark - DirectoryFilter
55 class DirectoryFilter
: public BRefFilter
{
58 virtual bool Filter(const entry_ref
* ref
,
59 BNode
* node
, struct stat_beos
* st
, const char* filetype
)
61 // ToDo: Fix this properly in Tracker
62 // If you create a folder, then rename it, node is NULL.
63 // The BeBook says: "Note that the function is never sent an
64 // abstract entry, so the node, st, and filetype arguments will
66 return node
== NULL
? false : node
->IsDirectory();
71 // #pragma mark - FileFormatMenuItem
74 class FileFormatMenuItem
: public BMenuItem
{
76 FileFormatMenuItem(media_file_format
* format
);
77 virtual ~FileFormatMenuItem();
79 media_file_format fFileFormat
;
83 FileFormatMenuItem::FileFormatMenuItem(media_file_format
* format
)
85 BMenuItem(format
->pretty_name
, new BMessage(FORMAT_SELECT_MESSAGE
))
87 memcpy(&fFileFormat
, format
, sizeof(fFileFormat
));
91 FileFormatMenuItem::~FileFormatMenuItem()
96 // #pragma mark - CodecMenuItem
99 class CodecMenuItem
: public BMenuItem
{
101 CodecMenuItem(media_codec_info
* ci
, uint32 message_type
);
102 virtual ~CodecMenuItem();
104 media_codec_info fCodecInfo
;
108 CodecMenuItem::CodecMenuItem(media_codec_info
* ci
, uint32 message_type
)
110 BMenuItem(ci
->pretty_name
, new BMessage(message_type
))
112 memcpy(&fCodecInfo
, ci
, sizeof(fCodecInfo
));
116 CodecMenuItem::~CodecMenuItem()
121 // #pragma mark - OutputBox
124 class OutputBox
: public BBox
{
126 OutputBox(border_style border
, BView
* child
);
127 virtual void FrameResized(float width
, float height
)
129 MediaConverterWindow
* window
130 = dynamic_cast<MediaConverterWindow
*>(Window());
132 window
->TruncateOutputFolderPath();
133 BBox::FrameResized(width
, height
);
138 OutputBox::OutputBox(border_style border
, BView
* child
)
145 // #pragma mark - MediaConverterWindow
148 MediaConverterWindow::MediaConverterWindow(BRect frame
)
150 BWindow(frame
, B_TRANSLATE_SYSTEM_NAME("MediaConverter"),
151 B_TITLED_WINDOW_LOOK
, B_NORMAL_WINDOW_FEEL
, B_NOT_ZOOMABLE
152 | B_NOT_V_RESIZABLE
| B_ASYNCHRONOUS_CONTROLS
153 | B_AUTO_UPDATE_SIZE_LIMITS
),
156 fSaveFilePanel(NULL
),
157 fOpenFilePanel(NULL
),
158 fOutputDirSpecified(false),
164 if (find_directory(B_USER_DIRECTORY
, &outputDir
) != B_OK
)
165 outputDir
.SetTo("/boot/home");
166 fOutputDir
.SetTo(outputDir
.Path());
168 fMenuBar
= new BMenuBar("menubar");
171 float padding
= be_control_look
->DefaultItemSpacing();
173 fListView
= new MediaFileListView();
174 fListView
->SetExplicitMinSize(BSize(padding
* kMinSourceWidth
, B_SIZE_UNSET
));
175 BScrollView
* scroller
= new BScrollView(NULL
, fListView
, 0, false, true);
177 // file list view box
178 fSourcesBox
= new BBox(B_FANCY_BORDER
, scroller
);
179 fSourcesBox
->SetLayout(new BGroupLayout(B_HORIZONTAL
, 0));
180 // fSourcesBox's layout adjusted in _UpdateLabels
183 fInfoView
= new MediaFileInfoView();
184 fInfoView
->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH
,
185 B_ALIGN_VERTICAL_UNSET
));
186 fInfoBox
= new BBox(B_FANCY_BORDER
, fInfoView
);
188 // output menu fields
189 fFormatMenu
= new BMenuField(NULL
, B_TRANSLATE("File format:"),
191 fAudioMenu
= new BMenuField(NULL
, B_TRANSLATE("Audio encoding:"),
193 fVideoMenu
= new BMenuField(NULL
, B_TRANSLATE("Video encoding:"),
197 fDestButton
= new BButton(B_TRANSLATE("Output folder"),
198 new BMessage(OUTPUT_FOLDER_MESSAGE
));
199 BAlignment
labelAlignment(be_control_look
->DefaultLabelAlignment());
200 fOutputFolder
= new BStringView(NULL
, outputDir
.Path());
201 fOutputFolder
->SetExplicitAlignment(labelAlignment
);
203 // start/end duration
204 fStartDurationTC
= new BTextControl(NULL
, "0", NULL
);
205 BLayoutItem
* startDuration
= fStartDurationTC
->CreateTextViewLayoutItem();
206 startDuration
->SetExplicitSize(BSize(padding
* kDurationWidth
, B_SIZE_UNSET
));
207 startDuration
->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT
,
208 B_ALIGN_VERTICAL_CENTER
));
209 fEndDurationTC
= new BTextControl(NULL
, "0", NULL
);
210 BLayoutItem
* endDuration
= fEndDurationTC
->CreateTextViewLayoutItem();
211 endDuration
->SetExplicitSize(BSize(padding
* kDurationWidth
, B_SIZE_UNSET
));
212 endDuration
->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT
,
213 B_ALIGN_VERTICAL_CENTER
));
216 fVideoQualitySlider
= new BSlider("VSlider", "" ,
217 new BMessage(VIDEO_QUALITY_CHANGED_MESSAGE
), 1, 100, B_HORIZONTAL
);
218 fVideoQualitySlider
->SetModificationMessage(
219 new BMessage(VIDEO_QUALITY_CHANGED_MESSAGE
));
220 fVideoQualitySlider
->SetValue(fVideoQuality
);
221 fVideoQualitySlider
->SetEnabled(false);
222 fVideoQualitySlider
->SetExplicitSize(BSize(padding
* kQualitySliderWidth
,
226 fAudioQualitySlider
= new BSlider("ASlider", "" ,
227 new BMessage(AUDIO_QUALITY_CHANGED_MESSAGE
), 1, 100, B_HORIZONTAL
);
228 fAudioQualitySlider
->SetModificationMessage(
229 new BMessage(AUDIO_QUALITY_CHANGED_MESSAGE
));
230 fAudioQualitySlider
->SetValue(fAudioQuality
);
231 fAudioQualitySlider
->SetEnabled(false);
232 fAudioQualitySlider
->SetExplicitSize(BSize(padding
* kQualitySliderWidth
,
236 BView
* outputGrid
= BLayoutBuilder::Grid
<>()
237 .Add(fFormatMenu
->CreateLabelLayoutItem(), 0, 0)
238 .Add(fFormatMenu
->CreateMenuBarLayoutItem(), 1, 0)
239 .Add(fAudioMenu
->CreateLabelLayoutItem(), 0, 1)
240 .Add(fAudioMenu
->CreateMenuBarLayoutItem(), 1, 1)
241 .Add(fVideoMenu
->CreateLabelLayoutItem(), 0, 2)
242 .Add(fVideoMenu
->CreateMenuBarLayoutItem(), 1, 2)
243 .Add(fDestButton
, 0, 3)
244 .Add(fOutputFolder
, 1, 3)
245 .Add(fStartDurationTC
->CreateLabelLayoutItem(), 0, 4)
246 .Add(startDuration
, 1, 4)
247 .Add(fEndDurationTC
->CreateLabelLayoutItem(), 0, 5)
248 .Add(endDuration
, 1, 5)
249 .Add(fVideoQualitySlider
, 0, 6, 2, 1)
250 .Add(fAudioQualitySlider
, 0, 7, 2, 1)
252 outputGrid
->SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH
,
253 B_ALIGN_USE_FULL_HEIGHT
));
254 fOutputBox
= new OutputBox(B_FANCY_BORDER
, outputGrid
);
255 fOutputBox
->SetLayout(new BGroupLayout(B_HORIZONTAL
, 0));
256 // fOutputBox's layout adjusted in _UpdateLabels
259 fPreviewButton
= new BButton(B_TRANSLATE("Preview"),
260 new BMessage(PREVIEW_MESSAGE
));
261 fPreviewButton
->SetEnabled(false);
263 fConvertButton
= new BButton(B_TRANSLATE("Convert"),
264 new BMessage(CONVERT_BUTTON_MESSAGE
));
267 fStatus
= new BStringView(NULL
, NULL
);
268 fStatus
->SetExplicitAlignment(labelAlignment
);
269 fFileStatus
= new BStringView(NULL
, NULL
);
270 fFileStatus
->SetExplicitAlignment(labelAlignment
);
272 SetStatusMessage("");
275 BLayoutBuilder::Group
<>(this, B_VERTICAL
, 0)
276 .SetInsets(0, 0, 0, 0)
278 .AddSplit(B_HORIZONTAL
, B_USE_DEFAULT_SPACING
)
279 .SetInsets(B_USE_WINDOW_SPACING
, B_USE_WINDOW_SPACING
,
280 B_USE_WINDOW_SPACING
, 0)
282 .AddGroup(B_VERTICAL
, B_USE_ITEM_SPACING
)
287 .AddGrid(B_USE_ITEM_SPACING
)
288 .SetInsets(B_USE_WINDOW_SPACING
, B_USE_DEFAULT_SPACING
,
289 B_USE_WINDOW_SPACING
, B_USE_WINDOW_SPACING
)
291 .Add(fFileStatus
, 0, 1)
292 .Add(BSpaceLayoutItem::CreateGlue(), 1, 0)
293 .Add(fPreviewButton
, 2, 0)
294 .Add(fConvertButton
, 3, 0)
299 MediaConverterWindow::~MediaConverterWindow()
301 delete fSaveFilePanel
;
302 delete fOpenFilePanel
;
310 MediaConverterWindow::MessageReceived(BMessage
* message
)
317 switch (message
->what
) {
318 #if B_BEOS_VERSION <= B_BEOS_VERSION_6
319 case B_LANGUAGE_CHANGED
:
324 case INIT_FORMAT_MENUS
:
326 if (CountSourceFiles() == 0)
327 SetEnabled(false, false);
331 if (message
->WasDropped()) {
332 DetachCurrentMessage();
333 message
->what
= B_REFS_RECEIVED
;
334 BMessenger(be_app
).SendMessage(message
);
339 case FORMAT_SELECT_MESSAGE
:
340 BuildAudioVideoMenus();
342 case AUDIO_CODEC_SELECT_MESSAGE
:
344 case VIDEO_CODEC_SELECT_MESSAGE
:
347 case CONVERT_BUTTON_MESSAGE
:
349 fConvertButton
->SetLabel(B_TRANSLATE("Cancel"));
351 SetStatusMessage(B_TRANSLATE("Convert"));
352 SetEnabled(false, true);
353 BMessenger(be_app
).SendMessage(START_CONVERSION_MESSAGE
);
354 } else if (!fCancelling
) {
356 SetStatusMessage(B_TRANSLATE("Cancelling" B_UTF8_ELLIPSIS
));
357 BMessenger(be_app
).SendMessage(CANCEL_CONVERSION_MESSAGE
);
361 case CONVERSION_DONE_MESSAGE
:
363 SetStatusMessage(fCancelling
? B_TRANSLATE("Conversion cancelled")
364 : B_TRANSLATE("Conversion completed"));
367 bool enable
= CountSourceFiles() > 0;
368 SetEnabled(enable
, enable
);
369 fConvertButton
->SetLabel(B_TRANSLATE("Convert"));
373 case OUTPUT_FOLDER_MESSAGE
:
374 // Execute Save Panel
375 if (fSaveFilePanel
== NULL
) {
376 BButton
* selectThisDir
;
378 BMessage
folderSelect(FOLDER_SELECT_MESSAGE
);
379 fSaveFilePanel
= new BFilePanel(B_OPEN_PANEL
, NULL
, NULL
,
380 B_DIRECTORY_NODE
, true, &folderSelect
, NULL
, false, true);
381 fSaveFilePanel
->SetButtonLabel(B_DEFAULT_BUTTON
,
382 B_TRANSLATE("Select"));
383 fSaveFilePanel
->SetTarget(this);
385 fSaveFilePanel
->Window()->Lock();
386 fSaveFilePanel
->Window()->SetTitle(
387 B_TRANSLATE("MediaConverter+:SaveDirectory"));
389 = fSaveFilePanel
->Window()->ChildAt(0)->FindView(
390 "cancel button")->Frame();
391 buttonRect
.right
= buttonRect
.left
- 20;
392 buttonRect
.left
= buttonRect
.right
- 130;
393 selectThisDir
= new BButton(buttonRect
, NULL
,
394 B_TRANSLATE("Select this folder"),
395 new BMessage(SELECT_THIS_DIR_MESSAGE
),
396 B_FOLLOW_BOTTOM
| B_FOLLOW_RIGHT
);
397 selectThisDir
->SetTarget(this);
398 fSaveFilePanel
->Window()->ChildAt(0)->AddChild(selectThisDir
);
399 fSaveFilePanel
->Window()->Unlock();
401 fSaveFilePanel
->SetRefFilter(new DirectoryFilter
);
403 fSaveFilePanel
->Show();
406 case FOLDER_SELECT_MESSAGE
:
407 // "SELECT" Button at Save Panel Pushed
408 fSaveFilePanel
->GetNextSelectedRef(&inRef
);
409 inEntry
.SetTo(&inRef
, true);
410 _SetOutputFolder(inEntry
);
411 fOutputDirSpecified
= true;
412 fSaveFilePanel
->Rewind();
415 case SELECT_THIS_DIR_MESSAGE
:
416 // "THIS DIR" Button at Save Panel Pushed
417 fSaveFilePanel
->GetPanelDirectory(&inRef
);
418 fSaveFilePanel
->Hide();
419 inEntry
.SetTo(&inRef
, true);
420 _SetOutputFolder(inEntry
);
421 fOutputDirSpecified
= true;
424 case OPEN_FILE_MESSAGE
:
425 // Execute Open Panel
426 if (!fOpenFilePanel
) {
427 fOpenFilePanel
= new BFilePanel(B_OPEN_PANEL
, NULL
, NULL
,
428 B_FILE_NODE
, true, NULL
, NULL
, false, true);
429 fOpenFilePanel
->SetTarget(this);
431 fOpenFilePanel
->Show();
434 case B_REFS_RECEIVED
:
435 // Media Files Seleced by Open Panel
436 DetachCurrentMessage();
437 message
->what
= B_REFS_RECEIVED
;
438 BMessenger(be_app
).SendMessage(message
);
445 MediaConverterWindow::QuitRequested();
448 case PREVIEW_MESSAGE
:
450 // Build the command line to launch the preview application.
451 // TODO: Launch the default app instead of hardcoded MediaPlayer!
452 int32 srcIndex
= fListView
->CurrentSelection();
453 BMediaFile
* inFile
= NULL
;
454 status_t status
= GetSourceFileAt(srcIndex
, &inFile
, &inRef
);
457 BString startPosString
;
460 if (status
== B_OK
) {
462 // NOTE: -pos argument is currently not supported by Haiku
464 startPosString
<< fStartDurationTC
->Text();
465 startPosString
<< "000";
466 argv
[1] = startPosString
.String();
468 status
= inEntry
.SetTo(&inRef
);
471 if (status
== B_OK
) {
472 status
= inEntry
.GetPath(&path
);
474 argv
[2] = path
.Path();
477 if (status
== B_OK
) {
478 status
= be_roster
->Launch(
479 "application/x-vnd.Haiku-MediaPlayer",
480 3, (char**)argv
, NULL
);
483 if (status
!= B_OK
&& status
!= B_ALREADY_RUNNING
) {
484 BString
errorString(B_TRANSLATE("Error launching: %strError%"));
485 errorString
.ReplaceFirst("%strError%", strerror(status
));
486 BAlert
* alert
= new BAlert(B_TRANSLATE("Error"),
487 errorString
.String(), B_TRANSLATE("OK"));
488 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
494 case VIDEO_QUALITY_CHANGED_MESSAGE
:
497 message
->FindInt32("be:value", &value
);
498 snprintf(buffer
, sizeof(buffer
),
499 B_TRANSLATE("Video quality: %3d%%"), (int8
)value
);
500 fVideoQualitySlider
->SetLabel(buffer
);
501 fVideoQuality
= value
;
505 case AUDIO_QUALITY_CHANGED_MESSAGE
:
508 message
->FindInt32("be:value", &value
);
509 snprintf(buffer
, sizeof(buffer
),
510 B_TRANSLATE("Audio quality: %3d%%"), (int8
)value
);
511 fAudioQualitySlider
->SetLabel(buffer
);
512 fAudioQuality
= value
;
517 BWindow::MessageReceived(message
);
523 MediaConverterWindow::QuitRequested()
526 BMessenger(be_app
).SendMessage(B_QUIT_REQUESTED
);
528 } else if (!fCancelling
) {
530 SetStatusMessage(B_TRANSLATE("Cancelling"));
531 BMessenger(be_app
).SendMessage(CANCEL_CONVERSION_MESSAGE
);
542 MediaConverterWindow::LanguageChanged()
547 BuildAudioVideoMenus();
549 fInfoView
->Invalidate();
555 MediaConverterWindow::BuildAudioVideoMenus()
557 BMenu
* menu
= fAudioMenu
->Menu();
560 // clear out old audio codec menu items
561 while ((item
= menu
->RemoveItem((int32
)0)) != NULL
)
564 bool separator
= true;
566 // get selected file format
567 FileFormatMenuItem
* ffmi
568 = (FileFormatMenuItem
*)fFormatMenu
->Menu()->FindMarked();
569 media_file_format
* mf_format
= &(ffmi
->fFileFormat
);
571 media_format format
, outfmt
;
572 memset(&format
, 0, sizeof(format
));
573 media_codec_info codec_info
;
577 // add available audio encoders to menu
578 format
.type
= B_MEDIA_RAW_AUDIO
;
579 format
.u
.raw_audio
= media_raw_audio_format::wildcard
;
580 while (get_next_encoder(&cookie
, mf_format
, &format
, &outfmt
, &codec_info
)
583 menu
->AddItem(new BMenuItem(
584 B_TRANSLATE_CONTEXT("No audio", "Audio codecs list"),
585 new BMessage(AUDIO_CODEC_SELECT_MESSAGE
)));
586 menu
->AddSeparatorItem();
590 cmi
= new CodecMenuItem(&codec_info
, AUDIO_CODEC_SELECT_MESSAGE
);
592 // reset media format struct
594 format.type = B_MEDIA_RAW_AUDIO;
595 format.u.raw_audio = media_raw_audio_format::wildcard;
599 // mark first audio encoder
600 item
= menu
->ItemAt(0);
602 fAudioMenu
->SetEnabled(fEnabled
);
603 fAudioQualitySlider
->SetEnabled(fEnabled
);
604 item
->SetMarked(true);
605 ((BInvoker
*)item
)->Invoke();
607 item
= new BMenuItem(
608 B_TRANSLATE_CONTEXT("None available", "Audio codecs"), NULL
);
610 item
->SetMarked(true);
611 fAudioMenu
->SetEnabled(false);
612 fAudioQualitySlider
->SetEnabled(false);
615 // clear out old video codec menu items
616 menu
= fVideoMenu
->Menu();
617 while ((item
= menu
->RemoveItem((int32
)0)) != NULL
)
622 // construct a generic video format. Some of these parameters
623 // seem silly, but are needed for R4.5.x, which is more picky
624 // than subsequent BeOS releases will be.
625 memset(&format
, 0, sizeof(format
));
626 format
.type
= B_MEDIA_RAW_VIDEO
;
627 format
.u
.raw_video
.last_active
= (uint32
)(240 - 1);
628 format
.u
.raw_video
.orientation
= B_VIDEO_TOP_LEFT_RIGHT
;
629 format
.u
.raw_video
.display
.format
= B_RGB32
;
630 format
.u
.raw_video
.display
.line_width
= (int32
)320;
631 format
.u
.raw_video
.display
.line_count
= (int32
)240;
632 format
.u
.raw_video
.display
.bytes_per_row
= 4 * 320;
634 // add available video encoders to menu
636 while (get_next_encoder(&cookie
, mf_format
, &format
, &outfmt
, &codec_info
)
639 menu
->AddItem(new BMenuItem(
640 B_TRANSLATE_CONTEXT("No video", "Video codecs list"),
641 new BMessage(VIDEO_CODEC_SELECT_MESSAGE
)));
642 menu
->AddSeparatorItem();
646 cmi
= new CodecMenuItem(&codec_info
, VIDEO_CODEC_SELECT_MESSAGE
);
650 // mark first video encoder
651 item
= menu
->ItemAt(0);
653 fVideoMenu
->SetEnabled(fEnabled
);
654 fVideoQualitySlider
->SetEnabled(fEnabled
);
655 item
->SetMarked(true);
656 ((BInvoker
*)item
)->Invoke();
658 item
= new BMenuItem(
659 B_TRANSLATE_CONTEXT("None available", "Video codecs"), NULL
);
661 item
->SetMarked(true);
662 fVideoMenu
->SetEnabled(false);
663 fVideoQualitySlider
->SetEnabled(false);
668 MediaConverterWindow::GetSelectedFormatInfo(media_file_format
** format
,
669 media_codec_info
** audio
, media_codec_info
** video
)
675 FileFormatMenuItem
* formatItem
=
676 dynamic_cast<FileFormatMenuItem
*>(fFormatMenu
->Menu()->FindMarked());
677 if (formatItem
!= NULL
)
678 *format
= &(formatItem
->fFileFormat
);
680 *audio
= *video
= NULL
;
681 CodecMenuItem
* codecItem
=
682 dynamic_cast<CodecMenuItem
*>(fAudioMenu
->Menu()->FindMarked());
683 if (codecItem
!= NULL
)
684 *audio
= &(codecItem
->fCodecInfo
);
686 codecItem
= dynamic_cast<CodecMenuItem
*>(fVideoMenu
->Menu()->FindMarked());
687 if (codecItem
!= NULL
)
688 *video
= &(codecItem
->fCodecInfo
);
693 MediaConverterWindow::BuildFormatMenu()
695 BMenu
* menu
= fFormatMenu
->Menu();
698 // clear out old format menu items
699 while ((item
= menu
->RemoveItem((int32
)0)) != NULL
)
702 // add menu items for each file format
703 media_file_format mfi
;
705 FileFormatMenuItem
* ff_item
;
706 while (get_next_file_format(&cookie
, &mfi
) == B_OK
) {
707 if ((mfi
.capabilities
& media_file_format::B_WRITABLE
) == 0)
709 ff_item
= new FileFormatMenuItem(&mfi
);
710 menu
->AddItem(ff_item
);
714 item
= menu
->ItemAt(0);
716 item
->SetMarked(true);
717 ((BInvoker
*)item
)->Invoke();
723 MediaConverterWindow::SetFileMessage(const char* message
)
725 fFileStatus
->SetText(message
);
730 MediaConverterWindow::SetStatusMessage(const char* message
)
732 fStatus
->SetText(message
);
740 MediaConverterWindow::AddSourceFile(BMediaFile
* file
, const entry_ref
& ref
)
742 if (!fListView
->AddMediaItem(file
, ref
))
745 if (!fOutputDirSpecified
) {
747 entry
.GetParent(&entry
);
748 _SetOutputFolder(entry
);
756 MediaConverterWindow::RemoveSourceFile(int32 index
)
758 delete fListView
->RemoveItem(index
);
759 fStartDurationTC
->SetText("0");
760 fEndDurationTC
->SetText("0");
765 MediaConverterWindow::CountSourceFiles()
767 return fListView
->CountItems();
772 MediaConverterWindow::GetSourceFileAt(int32 index
, BMediaFile
** _file
,
775 MediaFileListItem
* item
= dynamic_cast<MediaFileListItem
*>(
776 fListView
->ItemAt(index
));
778 *_file
= item
->fMediaFile
;
787 MediaConverterWindow::SourceFileSelectionChanged()
789 int32 selected
= fListView
->CurrentSelection();
790 BMediaFile
* file
= NULL
;
792 bool enabled
= GetSourceFileAt(selected
, &file
, &ref
) == B_OK
;
794 fPreviewButton
->SetEnabled(enabled
);
795 fVideoQualitySlider
->SetEnabled(enabled
);
796 fAudioQualitySlider
->SetEnabled(enabled
);
797 fStartDurationTC
->SetEnabled(enabled
);
798 fEndDurationTC
->SetEnabled(enabled
);
802 fInfoView
->Update(file
, &ref
);
803 // HACK: get the fInfoView to update the duration "synchronously"
805 duration
<< fInfoView
->Duration() / 1000;
809 // update duration text controls
810 fStartDurationTC
->SetText("0");
811 fEndDurationTC
->SetText(duration
.String());
819 MediaConverterWindow::SetEnabled(bool enabled
, bool convertEnabled
)
821 fConvertButton
->SetEnabled(convertEnabled
);
822 if (enabled
== fEnabled
)
825 fFormatMenu
->SetEnabled(enabled
);
826 fAudioMenu
->SetEnabled(enabled
);
827 fVideoMenu
->SetEnabled(enabled
);
828 fListView
->SetEnabled(enabled
);
829 fStartDurationTC
->SetEnabled(enabled
);
830 fEndDurationTC
->SetEnabled(enabled
);
837 MediaConverterWindow::IsEnabled()
844 MediaConverterWindow::StartDuration() const
846 return fStartDurationTC
->Text();
851 MediaConverterWindow::EndDuration() const
853 return fEndDurationTC
->Text();
858 MediaConverterWindow::OutputDirectory() const
865 MediaConverterWindow::SetAudioQualityLabel(const char* label
)
867 fAudioQualitySlider
->SetLabel(label
);
872 MediaConverterWindow::SetVideoQualityLabel(const char* label
)
874 fVideoQualitySlider
->SetLabel(label
);
879 MediaConverterWindow::TruncateOutputFolderPath()
882 fOutputDir
.GetEntry(&entry
);
884 entry
.GetPath(&path
);
885 BString
pathString(path
.Path());
886 float maxWidth
= fVideoMenu
->MenuBar()->Frame().Width();
888 fOutputFolder
->TruncateString(&pathString
, B_TRUNCATE_MIDDLE
, maxWidth
);
889 fOutputFolder
->SetText(pathString
.String());
890 if (fOutputFolder
->StringWidth(path
.Path()) > maxWidth
)
891 fOutputFolder
->SetToolTip(path
.Path());
893 fOutputFolder
->SetToolTip((const char*)NULL
);
901 MediaConverterWindow::_UpdateLabels()
903 if (fSourcesBox
!= NULL
) {
904 fSourcesBox
->SetLabel(B_TRANSLATE("Source files"));
905 _UpdateBBoxLayoutInsets(fSourcesBox
);
908 if (fInfoBox
!= NULL
)
909 fInfoBox
->SetLabel(B_TRANSLATE("File details"));
911 if (fOutputBox
!= NULL
) {
912 fOutputBox
->SetLabel(B_TRANSLATE("Output format"));
913 _UpdateBBoxLayoutInsets(fOutputBox
);
916 if (fConvertButton
!= NULL
)
917 fConvertButton
->SetLabel(B_TRANSLATE("Convert"));
919 if (fPreviewButton
!= NULL
)
920 fPreviewButton
->SetLabel(B_TRANSLATE("Preview"));
922 if (fDestButton
!= NULL
)
923 fDestButton
->SetLabel(B_TRANSLATE("Output folder"));
925 if (fVideoQualitySlider
!= NULL
) {
927 snprintf(buffer
, sizeof(buffer
), B_TRANSLATE("Video quality: %3d%%"),
928 (int8
)fVideoQuality
);
929 fVideoQualitySlider
->SetLabel(buffer
);
930 fVideoQualitySlider
->SetLimitLabels(B_TRANSLATE("Low"),
931 B_TRANSLATE("High"));
934 if (fAudioQualitySlider
!= NULL
) {
936 snprintf(buffer
, sizeof(buffer
), B_TRANSLATE("Audio quality: %3d%%"),
937 (int8
)fAudioQuality
);
938 fAudioQualitySlider
->SetLabel(buffer
);
939 fAudioQualitySlider
->SetLimitLabels(B_TRANSLATE("Low"),
940 B_TRANSLATE("High"));
943 if (fStartDurationTC
!= NULL
)
944 fStartDurationTC
->SetLabel(B_TRANSLATE("Start [ms]: "));
946 if (fEndDurationTC
!= NULL
)
947 fEndDurationTC
->SetLabel(B_TRANSLATE("End [ms]: "));
949 if (fFormatMenu
!= NULL
)
950 fFormatMenu
->SetLabel(B_TRANSLATE("File format:"));
952 if (fAudioMenu
!= NULL
)
953 fAudioMenu
->SetLabel(B_TRANSLATE("Audio encoding:"));
955 if (fVideoMenu
!= NULL
)
956 fVideoMenu
->SetLabel(B_TRANSLATE("Video encoding:"));
958 SetFileMessage(B_TRANSLATE("Drop media files onto this window"));
963 MediaConverterWindow::_UpdateBBoxLayoutInsets(BBox
* box
)
965 BTwoDimensionalLayout
* layout
966 = dynamic_cast<BTwoDimensionalLayout
*>(box
->GetLayout());
967 if (layout
!= NULL
) {
968 float padding
= be_control_look
->DefaultItemSpacing();
969 layout
->SetInsets(padding
, box
->TopBorderOffset() + padding
, padding
,
976 MediaConverterWindow::_DestroyMenu()
980 while ((menu
= fMenuBar
->SubmenuAt(0)) != NULL
) {
981 fMenuBar
->RemoveItem(menu
);
988 MediaConverterWindow::_CreateMenu()
993 menu
= new BMenu(B_TRANSLATE_CONTEXT("File", "Menu"));
994 item
= new BMenuItem(B_TRANSLATE_CONTEXT("Open" B_UTF8_ELLIPSIS
, "Menu"),
995 new BMessage(OPEN_FILE_MESSAGE
), 'O');
997 menu
->AddSeparatorItem();
998 item
= new BMenuItem(B_TRANSLATE_CONTEXT("Quit", "Menu"),
999 new BMessage(QUIT_MESSAGE
), 'Q');
1000 menu
->AddItem(item
);
1002 fMenuBar
->AddItem(menu
);
1007 MediaConverterWindow::_SetOutputFolder(BEntry entry
)
1010 entry
.GetPath(&path
);
1011 if (access(path
.Path(), W_OK
) != -1) {
1012 fOutputDir
.SetTo(&entry
);
1014 BString
errorString(B_TRANSLATE("Error writing to location: %strPath%."
1015 " Defaulting to location: /boot/home"));
1016 errorString
.ReplaceFirst("%strPath%", path
.Path());
1017 BAlert
* alert
= new BAlert(B_TRANSLATE("Error"),
1018 errorString
.String(), B_TRANSLATE("OK"));
1019 alert
->SetFlags(alert
->Flags() | B_CLOSE_ON_ESCAPE
);
1021 fOutputDir
.SetTo("/boot/home");
1023 TruncateOutputFolderPath();