1 /* $Id: MainWindow.cpp,v 1.14 2003/10/05 14:56:38 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://beos.titer.org/handbrake/>.
5 It may be used under the terms of the GNU General Public License. */
10 #include <Application.h>
13 #include <Directory.h>
15 #include <MenuField.h>
18 #include <PopUpMenu.h>
21 #include <StatusBar.h>
22 #include <StringView.h>
23 #include <TextControl.h>
24 #include <VolumeRoster.h>
26 #include "MainWindow.h"
28 #include "PictureWin.h"
30 #define DEFAULT_FILE "/boot/home/Desktop/Movie.avi"
31 #define WINDOW_RECT BRect( 0,0,400,405 )
33 #define BUTTON_ADVANCED 'badv'
34 #define BUTTON_FILE 'bfil'
35 #define BUTTON_PICTURE 'bpic'
36 #define BUTTON_START 'bsta'
37 #define BUTTON_CANCEL 'bcan'
38 #define BUTTON_SUSPEND 'bsus'
39 #define BUTTON_RESUME 'bres'
40 #define POPUP_AUDIO 'paud'
41 #define POPUP_TITLE 'ptit'
42 #define POPUP_VOLUME 'pvol'
43 #define SLIDER_AUDIO 'saud'
44 #define SLIDER_VIDEO 'svid'
46 /* HBBox : almost a simple BBox, unless we draw a horizontal line
47 before the "Picture" and "Advanced" buttons. There must be a
48 cleaner way to do this, but I'm not a expert GUI programmer. */
51 HBBox::HBBox( BRect rect )
57 void HBBox::Draw( BRect rect )
59 /* Inherited method */
63 SetHighColor( 120, 120, 120 );
64 SetLowColor( 255, 255, 255 );
65 StrokeLine( BPoint( 10, 265 ),
66 BPoint( Bounds().Width() - 10, 265 ),
68 StrokeLine( BPoint( 11, 266 ),
69 BPoint( Bounds().Width() - 10, 266 ),
73 HBVolumeItem::HBVolumeItem( HBVolume * volume )
74 : BMenuItem( "", new BMessage( POPUP_VOLUME ) )
78 SetLabel( fVolume->fName );
81 HBTitleItem::HBTitleItem( HBTitle * title )
82 : BMenuItem( "", new BMessage( POPUP_TITLE) )
86 char label[1024]; memset( label, 0, 1024 );
87 sprintf( label, "%d (%02lld:%02lld:%02lld)", fTitle->fIndex,
88 fTitle->fLength / 3600, ( fTitle->fLength % 3600 ) / 60,
89 fTitle->fLength % 60 );
93 HBAudioItem::HBAudioItem( HBAudio * audio )
94 : BMenuItem( "", new BMessage( POPUP_AUDIO ) )
98 SetLabel( fAudio ? fAudio->fDescription : "None" );
101 HBWindow::HBWindow( bool debug )
102 : BWindow( WINDOW_RECT, "HandBrake " VERSION, B_TITLED_WINDOW,
103 B_NOT_RESIZABLE | B_NOT_ZOOMABLE )
105 /* Center the window */
107 MoveTo( ( screen.Frame().Width() - Frame().Width() ) / 2,
108 ( screen.Frame().Height() - Frame().Height() ) / 2 );
110 /* -- GUI starts here -- */
114 /* Add a background view */
116 view = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
117 view->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
119 /* Add the settings box */
120 r = BRect( 10, 10, view->Bounds().Width() - 10,
121 view->Bounds().Height() - 85 );
122 fBox = new HBBox( r );
123 fBox->SetLabel( "Settings" );
126 r = BRect( 10, 15, fBox->Bounds().Width() - 10, 35 );
127 fVolumePopUp = new BPopUpMenu( "" );
128 fVolumeField = new BMenuField( r, NULL, "Volume :",
129 fVolumePopUp, true );
130 fBox->AddChild( fVolumeField );
133 r = BRect( 10, 45, fBox->Bounds().Width() - 10, 65 );
134 fTitlePopUp = new BPopUpMenu( "" );
135 fTitleField = new BMenuField( r, NULL, "Title :",
137 fBox->AddChild( fTitleField );
140 r = BRect( 10, 75, fBox->Bounds().Width() - 10, 95 );
141 fAudio1PopUp = new BPopUpMenu( "" );
142 fAudio1Field = new BMenuField( r, NULL, "Audio 1 :",
143 fAudio1PopUp, true );
144 fBox->AddChild( fAudio1Field );
147 r = BRect( 10, 105, fBox->Bounds().Width() - 10, 125 );
148 fAudio2PopUp = new BPopUpMenu( "" );
149 fAudio2Field = new BMenuField( r, NULL, "Audio 2 :",
150 fAudio2PopUp, true );
151 fBox->AddChild( fAudio2Field );
154 r = BRect( 10, 135, fBox->Bounds().Width() - 10, 165 );
155 fVideoSlider = new BSlider( r, NULL, "Video bitrate : 1024 kbps",
156 new BMessage( SLIDER_VIDEO ),
157 128, 4096, B_TRIANGLE_THUMB );
158 fVideoSlider->SetValue( 1024 );
159 fBox->AddChild( fVideoSlider );
162 r = BRect( 10, 175, fBox->Bounds().Width() - 10, 205 );
163 fAudioSlider = new BSlider( r, NULL, "Audio bitrate : 128 kbps",
164 new BMessage( SLIDER_AUDIO ),
165 64, 384, B_TRIANGLE_THUMB );
166 fAudioSlider->SetValue( 128 );
167 fBox->AddChild( fAudioSlider );
169 /* Destination file */
170 r = BRect( 10, 215, fBox->Bounds().Width() - 10, 230 );
171 fFileString = new BStringView( r, NULL, "Destination file :" );
172 fBox->AddChild( fFileString );
173 r = BRect( 10, 235, fBox->Bounds().Width() - 90, 255 );
174 fFileControl = new BTextControl( r, NULL, "", DEFAULT_FILE,
176 fFileControl->SetDivider( 0 );
177 fBox->AddChild( fFileControl );
178 r = BRect( fBox->Bounds().Width() - 80, 230,
179 fBox->Bounds().Width() - 10, 255 );
180 fFileButton = new BButton( r, NULL, "Browse...",
181 new BMessage( BUTTON_FILE ) );
182 fBox->AddChild( fFileButton );
184 /* Settings buttons */
185 r = BRect( fBox->Bounds().Width() - 200, 275,
186 fBox->Bounds().Width() - 100, 300 );
187 fPictureButton = new BButton( r, NULL, "Picture settings...",
188 new BMessage( BUTTON_PICTURE ) );
189 fBox->AddChild( fPictureButton );
191 r = BRect( fBox->Bounds().Width() - 90, 275,
192 fBox->Bounds().Width() - 10, 300 );
193 fAdvancedButton = new BButton( r, NULL, "Advanced...",
194 new BMessage( BUTTON_ADVANCED ) );
195 fBox->AddChild( fAdvancedButton );
197 view->AddChild( fBox );
200 r = BRect( 10, view->Bounds().Height() - 75,
201 view->Bounds().Width() - 10, view->Bounds().Height() - 45 );
202 fStatusBar = new BStatusBar( r, NULL, NULL );
203 fStatusBar->SetMaxValue( 1.0 );
204 view->AddChild( fStatusBar );
207 r = BRect( view->Bounds().Width() - 240, view->Bounds().Height() - 35,
208 view->Bounds().Width() - 170, view->Bounds().Height() - 10 );
209 BButton * aboutButton;
210 aboutButton = new BButton( r, NULL, "About...",
211 new BMessage( B_ABOUT_REQUESTED ) );
212 view->AddChild( aboutButton );
214 r = BRect( view->Bounds().Width() - 160, view->Bounds().Height() - 35,
215 view->Bounds().Width() - 90, view->Bounds().Height() - 10 );
216 fSuspendButton = new BButton( r, NULL, "Suspend",
217 new BMessage( BUTTON_SUSPEND ) );
218 view->AddChild( fSuspendButton );
220 r = BRect( view->Bounds().Width() - 80, view->Bounds().Height() - 35,
221 view->Bounds().Width() - 10, view->Bounds().Height() - 10 );
222 fStartButton = new BButton( r, NULL, "Start !",
223 new BMessage( BUTTON_START ) );
224 view->AddChild( fStartButton );
228 /* -- GUI ends here -- */
230 /* Init libhb & launch the manager thread */
231 fManager = new HBManager( debug );
233 /* Detects DVD drives & VOB folders, then tell libhb to scan it */
236 /* Update the interface */
237 fUpdateThread = spawn_thread( (int32 (*)(void *)) UpdateInterface,
238 "interface", B_DISPLAY_PRIORITY, this );
239 resume_thread( fUpdateThread );
242 bool HBWindow::QuitRequested()
245 kill_thread( fUpdateThread );
248 /* Stop the application */
249 be_app->PostMessage( B_QUIT_REQUESTED );
253 void HBWindow::MessageReceived( BMessage * message )
255 switch( message->what )
257 case B_ABOUT_REQUESTED:
260 alert = new BAlert( "About HandBrake",
261 "HandBrake " VERSION "\n\n"
262 "by Eric Petit <titer@videolan.org>\n"
263 "Homepage : <http://beos.titer.org/handbrake/>\n\n"
264 "No, you don't want to know where this stupid app "
265 "name comes from.\n\n"
266 "Thanks to BGA for pointing out very cool bugs ;)",
272 case BUTTON_ADVANCED:
281 ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle;
282 HBPictureWin * pictureWin = new HBPictureWin( fManager, title );
290 ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle;
292 ((HBAudioItem*) fAudio1PopUp->FindMarked())->fAudio;
294 ((HBAudioItem*) fAudio2PopUp->FindMarked())->fAudio;
296 title->fBitrate = fVideoSlider->Value();
299 audio1->fOutBitrate = fAudioSlider->Value();
303 audio2->fOutBitrate = fAudioSlider->Value();
306 fManager->StartRip( title, audio1, audio2,
307 (char*) fFileControl->Text() );
316 fManager->SuspendRip();
320 fManager->ResumeRip();
329 ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle;
331 /* Empty audio popups */
332 HBAudioItem * audioItem;
333 while( ( audioItem = (HBAudioItem*) fAudio1PopUp->ItemAt( 0 ) ) )
335 fAudio1PopUp->RemoveItem( audioItem );
338 while( ( audioItem = (HBAudioItem*) fAudio2PopUp->ItemAt( 0 ) ) )
340 fAudio2PopUp->RemoveItem( audioItem );
346 i < title->fAudioList->CountItems();
349 audio = (HBAudio*) title->fAudioList->ItemAt( i );
350 fAudio1PopUp->AddItem( new HBAudioItem( audio ) );
351 fAudio2PopUp->AddItem( new HBAudioItem( audio ) );
353 fAudio1PopUp->AddItem( new HBAudioItem( NULL ) );
354 fAudio2PopUp->AddItem( new HBAudioItem( NULL ) );
355 ((HBAudioItem*) fAudio1PopUp->ItemAt( 0 ))->SetMarked( true );
356 ((HBAudioItem*) fAudio2PopUp->ItemAt(
357 fAudio2PopUp->CountItems() - 1 ))->SetMarked( true );
367 char label[64]; memset( label, 0, 64 );
368 snprintf( label, 128, "Audio bitrate : %ld kbps",
369 fAudioSlider->Value() );
370 fAudioSlider->SetLabel( label );
376 char label[64]; memset( label, 0, 64 );
377 snprintf( label, 128, "Video bitrate : %ld kbps",
378 fVideoSlider->Value() );
379 fVideoSlider->SetLabel( label );
384 BWindow::MessageReceived( message );
390 void HBWindow::ScanVolumes()
392 BVolumeRoster * roster = new BVolumeRoster();
393 BVolume * bVolume = new BVolume();
396 device_geometry geometry;
399 HBList * volumeList = new HBList();
401 /* Parse mounted volumes */
402 while( roster->GetNextVolume( bVolume ) == B_NO_ERROR )
404 /* open() and ioctl() for more informations */
405 fs_stat_dev( bVolume->Device(), &info );
406 if( ( device = open( info.device_name, O_RDONLY ) ) < 0 )
411 if( ioctl( device, B_GET_GEOMETRY, &geometry,
412 sizeof( geometry ) ) < 0 )
418 /* Get the volume name */
419 char volumeName[B_FILE_NAME_LENGTH];
420 bVolume->GetName( volumeName );
422 if( bVolume->IsReadOnly() && geometry.device_type == B_CD )
425 volume = new HBVolume( info.device_name, volumeName );
426 volumeList->AddItem( volume );
428 else if( geometry.device_type == B_DISK )
430 /* May be a hard drive. Look for VIDEO_TS folders on it */
431 BQuery * query = new BQuery();
433 if( query->SetVolume( bVolume ) != B_OK )
439 if( query->SetPredicate( "name = VIDEO_TS.BUP" ) != B_OK )
447 BEntry entry, parentEntry;
449 while( query->GetNextEntry( &entry ) == B_OK )
451 entry.GetParent( &parentEntry );
452 parentEntry.GetPath( &path );
454 volume = new HBVolume( (char*) path.Path() );
455 volumeList->AddItem( volume );
462 fManager->ScanVolumes( volumeList );
465 void HBWindow::UpdateInterface( HBWindow * _this )
469 _this->_UpdateInterface();
474 void HBWindow::_UpdateInterface()
476 if( !fManager->NeedUpdate() )
481 HBStatus status = fManager->GetStatus();
485 fprintf( stderr, "Lock() failed\n" );
489 EnableInterface( status.fMode );
491 switch( status.fMode )
496 case HB_MODE_SCANNING:
498 char text[1024]; memset( text, 0, 1024 );
499 sprintf( text, "Scanning %s, title %d...",
500 status.fScannedVolume, status.fScannedTitle );
501 fStatusBar->Update( - fStatusBar->CurrentValue(), text );
505 case HB_MODE_SCANDONE:
509 i < status.fVolumeList->CountItems();
512 volume = (HBVolume*) status.fVolumeList->ItemAt( i );
513 fVolumePopUp->AddItem( new HBVolumeItem( volume ) );
515 ((HBVolumeItem*) fVolumePopUp->ItemAt( 0 ))->SetMarked( true );
518 volume = (HBVolume*) status.fVolumeList->ItemAt( 0 );
520 i < volume->fTitleList->CountItems();
523 title = (HBTitle*) volume->fTitleList->ItemAt( i );
524 fTitlePopUp->AddItem( new HBTitleItem( title ) );
526 ((HBTitleItem*) fTitlePopUp->ItemAt( 0 ))->SetMarked( true );
529 title = (HBTitle*) volume->fTitleList->ItemAt( 0 );
531 i < title->fAudioList->CountItems();
534 audio = (HBAudio*) title->fAudioList->ItemAt( i );
535 fAudio1PopUp->AddItem( new HBAudioItem( audio ) );
536 fAudio2PopUp->AddItem( new HBAudioItem( audio ) );
538 fAudio1PopUp->AddItem( new HBAudioItem( NULL ) );
539 fAudio2PopUp->AddItem( new HBAudioItem( NULL ) );
540 ((HBAudioItem*) fAudio1PopUp->ItemAt( 0 ))->SetMarked( true );
541 ((HBAudioItem*) fAudio2PopUp->ItemAt(
542 fAudio2PopUp->CountItems() - 1 ))->SetMarked( true );
544 fStatusBar->Update( - fStatusBar->CurrentValue(),
545 "Ready. Press 'Start' to rip." );
549 case HB_MODE_ENCODING:
551 char text[1024]; memset( text, 0, 1024 );
553 "Encoding : %.2f %%, %.2f fps (%02d:%02d:%02d remaining)",
554 100 * status.fPosition, status.fFrameRate,
555 status.fRemainingTime / 3600,
556 ( status.fRemainingTime % 3600 ) / 60,
557 status.fRemainingTime % 60 );
558 fStatusBar->Update( status.fPosition -
559 fStatusBar->CurrentValue(), text );
563 case HB_MODE_SUSPENDED:
565 char text[1024]; memset( text, 0, 1024 );
566 sprintf( text, "Encoding : %.2f %%, %.2f fps (Paused)",
567 100 * status.fPosition, status.fFrameRate );
568 fStatusBar->Update( status.fPosition -
569 fStatusBar->CurrentValue(), text );
576 case HB_MODE_CANCELED:
589 void HBWindow::EnableInterface( HBMode mode )
591 if( mode == fOldMode && mode != HB_MODE_UNDEF )
600 fAdvancedButton->SetEnabled( false );
601 fFileButton->SetEnabled( false );
602 fPictureButton->SetEnabled( false );
603 fStartButton->SetEnabled( false );
604 fSuspendButton->SetEnabled( false );
605 fAudio1Field->SetEnabled( false );
606 fAudio2Field->SetEnabled( false );
607 fTitleField->SetEnabled( false );
608 fVolumeField->SetEnabled( false );
609 fAudioSlider->SetEnabled( false );
610 fVideoSlider->SetEnabled( false );
611 fFileString->SetHighColor( 156, 156, 156 );
612 fFileString->Invalidate();
613 fFileControl->SetEnabled( false );
617 case HB_MODE_SCANNING:
619 fAdvancedButton->SetEnabled( true );
620 fFileButton->SetEnabled( true );
621 fPictureButton->SetEnabled( false );
622 fStartButton->SetEnabled( false );
623 fSuspendButton->SetEnabled( false );
624 fAudio1Field->SetEnabled( false );
625 fAudio2Field->SetEnabled( false );
626 fTitleField->SetEnabled( false );
627 fVolumeField->SetEnabled( false );
628 fAudioSlider->SetEnabled( true );
629 fVideoSlider->SetEnabled( true );
630 fFileString->SetHighColor( 0, 0, 0 );
631 fFileString->Invalidate();
632 fFileControl->SetEnabled( true );
636 case HB_MODE_SCANDONE:
638 fAdvancedButton->SetEnabled( true );
639 fFileButton->SetEnabled( true );
640 fPictureButton->SetEnabled( true );
641 fStartButton->SetLabel( "Start" );
642 fStartButton->SetMessage( new BMessage( BUTTON_START ) );
643 fStartButton->SetEnabled( true );
644 fSuspendButton->SetEnabled( false );
645 fAudio1Field->SetEnabled( true );
646 fAudio2Field->SetEnabled( true );
647 fTitleField->SetEnabled( true );
648 fVolumeField->SetEnabled( true );
649 fAudioSlider->SetEnabled( true );
650 fVideoSlider->SetEnabled( true );
651 fFileString->SetHighColor( 0, 0, 0 );
652 fFileString->Invalidate();
653 fFileControl->SetEnabled( true );
657 case HB_MODE_ENCODING:
659 fFileButton->SetEnabled( false );
660 fPictureButton->SetEnabled( false );
661 fStartButton->SetLabel( "Cancel" );
662 fStartButton->SetMessage( new BMessage( BUTTON_CANCEL ) );
663 fStartButton->SetEnabled( true );
664 fSuspendButton->SetLabel( "Suspend" );
665 fSuspendButton->SetMessage( new BMessage( BUTTON_SUSPEND ) );
666 fSuspendButton->SetEnabled( true );
667 fAudio1Field->SetEnabled( false );
668 fAudio2Field->SetEnabled( false );
669 fTitleField->SetEnabled( false );
670 fVolumeField->SetEnabled( false );
671 fAudioSlider->SetEnabled( false );
672 fVideoSlider->SetEnabled( false );
673 fFileString->SetHighColor( 156, 156, 156 );
674 fFileString->Invalidate();
675 fFileControl->SetEnabled( false );
679 case HB_MODE_SUSPENDED:
681 fFileButton->SetEnabled( false );
682 fPictureButton->SetEnabled( false );
683 fStartButton->SetLabel( "Cancel" );
684 fStartButton->SetMessage( new BMessage( BUTTON_CANCEL ) );
685 fStartButton->SetEnabled( true );
686 fSuspendButton->SetLabel( "Resume" );
687 fSuspendButton->SetMessage( new BMessage( BUTTON_RESUME ) );
688 fSuspendButton->SetEnabled( true );
689 fAudio1Field->SetEnabled( false );
690 fAudio2Field->SetEnabled( false );
691 fTitleField->SetEnabled( false );
692 fVolumeField->SetEnabled( false );
693 fAudioSlider->SetEnabled( false );
694 fVideoSlider->SetEnabled( false );
695 fFileString->SetHighColor( 156, 156, 156 );
696 fFileString->Invalidate();
697 fFileControl->SetEnabled( false );
703 fFileButton->SetEnabled( false );
704 fPictureButton->SetEnabled( false );
705 fStartButton->SetEnabled( true );
706 fSuspendButton->SetEnabled( true );
707 fAudio1Field->SetEnabled( false );
708 fAudio2Field->SetEnabled( false );
709 fTitleField->SetEnabled( false );
710 fVolumeField->SetEnabled( false );
711 fAudioSlider->SetEnabled( false );
712 fVideoSlider->SetEnabled( false );
713 fFileString->SetHighColor( 156, 156, 156 );
714 fFileString->Invalidate();
715 fFileControl->SetEnabled( false );
719 case HB_MODE_CANCELED:
721 fFileButton->SetEnabled( false );
722 fPictureButton->SetEnabled( false );
723 fStartButton->SetEnabled( true );
724 fSuspendButton->SetEnabled( true );
725 fAudio1Field->SetEnabled( false );
726 fAudio2Field->SetEnabled( false );
727 fTitleField->SetEnabled( false );
728 fVolumeField->SetEnabled( false );
729 fAudioSlider->SetEnabled( false );
730 fVideoSlider->SetEnabled( false );
731 fFileString->SetHighColor( 156, 156, 156 );
732 fFileString->Invalidate();
733 fFileControl->SetEnabled( false );
739 fFileButton->SetEnabled( false );
740 fPictureButton->SetEnabled( false );
741 fStartButton->SetEnabled( true );
742 fSuspendButton->SetEnabled( true );
743 fAudio1Field->SetEnabled( false );
744 fAudio2Field->SetEnabled( false );
745 fTitleField->SetEnabled( false );
746 fVolumeField->SetEnabled( false );
747 fAudioSlider->SetEnabled( false );
748 fVideoSlider->SetEnabled( false );
749 fFileString->SetHighColor( 156, 156, 156 );
750 fFileString->Invalidate();
751 fFileControl->SetEnabled( false );