OSDN Git Service

HandBrake 0.4
authorroot <root@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 14 Jan 2006 12:56:59 +0000 (12:56 +0000)
committerroot <root@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 14 Jan 2006 12:56:59 +0000 (12:56 +0000)
git-svn-id: svn://localhost/HandBrake/trunk@5 b64f7644-9d1e-0410-96f1-a4d463321fa5

48 files changed:
Jamfile
NEWS
TODO
beos/HandBrake.cpp
beos/HandBrake.h
beos/HandBrake.rsrc [new file with mode: 0644]
beos/MainWindow.cpp
beos/MainWindow.h
beos/RipView.cpp [new file with mode: 0644]
beos/RipView.h [new file with mode: 0644]
beos/ScanView.cpp [new file with mode: 0644]
beos/ScanView.h [new file with mode: 0644]
core/Ac3Decoder.cpp
core/Ac3Decoder.h
core/AviMuxer.cpp
core/Common.cpp
core/Common.h
core/DVDReader.cpp
core/Fifo.cpp
core/Manager.cpp
core/Manager.h
core/Mp3Encoder.cpp
core/Mp3Encoder.h
core/Mpeg2Decoder.cpp
core/Mpeg2Decoder.h
core/Mpeg4Encoder.cpp
core/Mpeg4Encoder.h
core/MpegDemux.cpp
core/MpegDemux.h
core/Resizer.cpp
core/Resizer.h
core/Scanner.cpp
core/Thread.cpp
core/Thread.h
core/Worker.cpp [new file with mode: 0644]
core/Worker.h [new file with mode: 0644]
macosx/Controller.h [moved from macosx/HBController.h with 66% similarity]
macosx/Controller.mm [moved from macosx/HBController.mm with 61% similarity]
macosx/English.lproj/InfoPlist.strings
macosx/English.lproj/MainMenu.nib/classes.nib
macosx/English.lproj/MainMenu.nib/info.nib
macosx/English.lproj/MainMenu.nib/objects.nib
macosx/HandBrake.pbproj/project.pbxproj
macosx/PictureGLView.h
macosx/PictureGLView.mm
macosx/TargetSizeField.h [new file with mode: 0644]
macosx/TargetSizeField.mm [new file with mode: 0644]
test/Test.cpp

diff --git a/Jamfile b/Jamfile
index 31e4874..a900913 100644 (file)
--- a/Jamfile
+++ b/Jamfile
@@ -1,10 +1,10 @@
-# $Id: Jamfile,v 1.33 2003/10/06 21:21:27 titer Exp $
+# $Id: Jamfile,v 1.38 2003/10/13 23:46:41 titer Exp $
 #
 # This file is part of the HandBrake source code.
 # Homepage: <http://beos.titer.org/handbrake/>.
 # It may be used under the terms of the GNU General Public License.
 
-HB_VERSION = 0.3 ;
+HB_VERSION = 0.4 ;
 
 # Compilers
 C++  = g++ ;
@@ -28,7 +28,7 @@ LINKLIBS = -ldvdplay -ldvdread -ldvdcss -lmpeg2 -lavcodec -la52 -lmp3lame ;
 if $(OS) = BEOS
 {
     C++FLAGS += -Wno-multichar ;
-    LINKLIBS += -lbe ;
+    LINKLIBS += -lbe -ltracker ;
 }
 else if $(OS) = LINUX
 {
@@ -65,7 +65,7 @@ Library core/libhb : core/Ac3Decoder.cpp core/AviMuxer.cpp
                      core/Manager.cpp core/Mp3Encoder.cpp
                      core/Mpeg2Decoder.cpp core/Mpeg4Encoder.cpp
                     core/MpegDemux.cpp core/Resizer.cpp
-                    core/Scanner.cpp core/Thread.cpp ;
+                    core/Scanner.cpp core/Thread.cpp core/Worker.cpp ;
 
 LinkLibraries HBTest : core/libhb.a ;
 Main HBTest : test/Test.cpp ;
@@ -74,7 +74,8 @@ if $(OS) = BEOS
 {
     LinkLibraries HandBrake : core/libhb.a ;
     Main HandBrake : beos/HandBrake.cpp beos/MainWindow.cpp
-                     beos/PictureWin.cpp ;
+                     beos/PictureWin.cpp beos/ScanView.cpp
+                    beos/RipView.cpp ;
 }
 
 if $(OS) = MACOSX
diff --git a/NEWS b/NEWS
index 9160a55..b3bc5cb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,10 @@
-$Id: NEWS,v 1.9 2003/10/06 21:21:27 titer Exp $
+$Id: NEWS,v 1.11 2003/10/13 15:35:38 titer Exp $
+
+Changes between 0.3 and 0.4
+ - Better multithreading
+ - Allow the user to specify a target size instead of bitrate
+ - Misc GUI enhancements
+ - Use low-priority threads on OS X
 
 Changes between 0.2 and 0.3
  - OSX & Linux ports
diff --git a/TODO b/TODO
index fcbbe2a..127cc12 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,10 +1,8 @@
 - General
-  + Keep detecting DVDs after launching
-  + Possible to specify a target size
   + Use the DVD name in popup and for the name of the created file
   + Show the current pass
+  + Should be able to boost the audio volume
 
 - OSX port
-  + Check thread priorities
-  + "Ding" when done + window + "Ahuh"
   + Preview in a drawer
+  + Prompt before overwriting a file
index b1b386a..b5f1319 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: HandBrake.cpp,v 1.6 2003/09/30 14:38:15 titer Exp $
+/* $Id: HandBrake.cpp,v 1.8 2003/10/13 22:23:02 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
 
 void SigHandler( int signal )
 {
+    /* Ugly way to exit cleanly when hitting Ctrl-C */
     ((HBApp*) be_app)->fWindow->PostMessage( B_QUIT_REQUESTED );
 }
 
-int main( int argc, char ** argv )
+int main()
 {
     signal( SIGINT,  SigHandler );
     signal( SIGHUP,  SigHandler );
     signal( SIGQUIT, SigHandler );
 
-    int c;
-    bool debug = false;
-    while( ( c = getopt( argc, argv, "v" ) ) != -1 )
-    {
-        switch( c )
-        {
-            case 'v':
-                debug = true;
-                break;
-
-            default:
-                break;
-        }
-    }
-
     /* Run the BApplication */
-    HBApp * app = new HBApp( debug );
+    HBApp * app = new HBApp();
     app->Run();
     delete app;
     return 0;
 }
 
 /* Constructor */
-HBApp::HBApp( bool debug )
-    : BApplication( "application/x-vnd.titer-handbrake" )
+HBApp::HBApp()
+    : BApplication("application/x-vnd.titer-handbrake" )
 {
-    fWindow = new HBWindow( debug );
+    fWindow = new MainWindow();
     fWindow->Show();
 }
 
+void HBApp::MessageReceived( BMessage * message )
+{
+    switch( message->what )
+    {
+        case B_SAVE_REQUESTED:
+            fWindow->PostMessage( message );
+            break;
+
+        default:
+            BApplication::MessageReceived( message );
+            break;
+    }
+}
+
+void HBApp::RefsReceived( BMessage * message )
+{
+    fWindow->PostMessage( message );
+}
+
index 72234e1..7035b54 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: HandBrake.h,v 1.5 2003/09/30 14:38:15 titer Exp $
+/* $Id: HandBrake.h,v 1.7 2003/10/13 22:23:02 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -9,14 +9,16 @@
 
 #include <Application.h>
 
-class HBWindow;
+class MainWindow;
 
 class HBApp : public BApplication
 {
     public:
-                   HBApp( bool debug );
+                     HBApp();
+        void         MessageReceived( BMessage * message );
+        void         RefsReceived( BMessage * message );
 
-        HBWindow * fWindow;
+        MainWindow * fWindow;
 };
 
 #endif
diff --git a/beos/HandBrake.rsrc b/beos/HandBrake.rsrc
new file mode 100644 (file)
index 0000000..d9f87ee
Binary files /dev/null and b/beos/HandBrake.rsrc differ
index ca18537..613cf21 100644 (file)
-/* $Id: MainWindow.cpp,v 1.14 2003/10/05 14:56:38 titer Exp $
+/* $Id: MainWindow.cpp,v 1.19 2003/10/13 22:23:02 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
    It may be used under the terms of the GNU General Public License. */
 
-#include <fs_info.h>
-#include <sys/ioctl.h>
 #include <Alert.h>
 #include <Application.h>
-#include <Box.h>
-#include <Button.h>
-#include <Directory.h>
-#include <Drivers.h>
-#include <MenuField.h>
-#include <Path.h>
-#include <Query.h>
-#include <PopUpMenu.h>
 #include <Screen.h>
-#include <Slider.h>
-#include <StatusBar.h>
-#include <StringView.h>
-#include <TextControl.h>
-#include <VolumeRoster.h>
 
-#include "MainWindow.h"
 #include "Manager.h"
-#include "PictureWin.h"
-
-#define DEFAULT_FILE          "/boot/home/Desktop/Movie.avi"
-#define WINDOW_RECT           BRect( 0,0,400,405 )
-
-#define BUTTON_ADVANCED 'badv'
-#define BUTTON_FILE     'bfil'
-#define BUTTON_PICTURE  'bpic'
-#define BUTTON_START    'bsta'
-#define BUTTON_CANCEL   'bcan'
-#define BUTTON_SUSPEND  'bsus'
-#define BUTTON_RESUME   'bres'
-#define POPUP_AUDIO     'paud'
-#define POPUP_TITLE     'ptit'
-#define POPUP_VOLUME    'pvol'
-#define SLIDER_AUDIO    'saud'
-#define SLIDER_VIDEO    'svid'
-
-/* HBBox : almost a simple BBox, unless we draw a horizontal line
-   before the "Picture" and "Advanced" buttons. There must be a
-   cleaner way to do this, but I'm not a expert GUI programmer. */
-
-/* Constructor */
-HBBox::HBBox( BRect rect )
-    : BBox( rect, NULL )
-{
-}
-
-/* Draw */
-void HBBox::Draw( BRect rect )
-{
-    /* Inherited method */
-       BBox::Draw( rect );
-
-    /* Draw the line */
-    SetHighColor( 120, 120, 120 );
-       SetLowColor( 255, 255, 255 );
-       StrokeLine( BPoint( 10, 265 ),
-                BPoint( Bounds().Width() - 10, 265 ),
-                B_SOLID_HIGH );
-       StrokeLine( BPoint( 11, 266 ),
-                   BPoint( Bounds().Width() - 10, 266 ),
-                   B_SOLID_LOW );
-}
-
-HBVolumeItem::HBVolumeItem( HBVolume * volume )
-    : BMenuItem( "", new BMessage( POPUP_VOLUME ) )
-{
-    fVolume = volume;
-
-    SetLabel( fVolume->fName );
-}
-
-HBTitleItem::HBTitleItem( HBTitle * title )
-    : BMenuItem( "", new BMessage( POPUP_TITLE) )
-{
-    fTitle = title;
-
-    char label[1024]; memset( label, 0, 1024 );
-    sprintf( label, "%d (%02lld:%02lld:%02lld)", fTitle->fIndex,
-             fTitle->fLength / 3600, ( fTitle->fLength % 3600 ) / 60,
-             fTitle->fLength % 60 );
-    SetLabel( label );
-}
-
-HBAudioItem::HBAudioItem( HBAudio * audio )
-    : BMenuItem( "", new BMessage( POPUP_AUDIO ) )
-{
-    fAudio = audio;
-
-    SetLabel( fAudio ? fAudio->fDescription : "None" );
-}
+#include "MainWindow.h"
+#include "ScanView.h"
+#include "RipView.h"
 
-HBWindow::HBWindow( bool debug )
-    : BWindow( WINDOW_RECT, "HandBrake " VERSION, B_TITLED_WINDOW,
+MainWindow::MainWindow()
+    : BWindow( BRect( 0,0,10,10 ), "HandBrake " VERSION, B_TITLED_WINDOW,
                B_NOT_RESIZABLE | B_NOT_ZOOMABLE )
 {
-    /* Center the window */
-    BScreen screen;
-    MoveTo( ( screen.Frame().Width() - Frame().Width() ) / 2,
-            ( screen.Frame().Height() - Frame().Height() ) / 2 );
-
-    /* -- GUI starts here -- */
-
-    BRect r;
-
-    /* Add a background view */
-    BView * view;
-    view = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
-    view->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
-
-    /* Add the settings box */
-    r = BRect( 10, 10, view->Bounds().Width() - 10,
-               view->Bounds().Height() - 85 );
-    fBox = new HBBox( r );
-    fBox->SetLabel( "Settings" );
-
-    /* Volume */
-    r = BRect( 10, 15, fBox->Bounds().Width() - 10, 35 );
-    fVolumePopUp = new BPopUpMenu( "" );
-    fVolumeField = new BMenuField( r, NULL, "Volume :",
-                                   fVolumePopUp, true );
-    fBox->AddChild( fVolumeField );
-
-    /* Title */
-    r = BRect( 10, 45, fBox->Bounds().Width() - 10, 65 );
-    fTitlePopUp = new BPopUpMenu( "" );
-    fTitleField = new BMenuField( r, NULL, "Title :",
-                                  fTitlePopUp, true );
-    fBox->AddChild( fTitleField );
-
-    /* Audio 1 */
-    r = BRect( 10, 75, fBox->Bounds().Width() - 10, 95 );
-    fAudio1PopUp = new BPopUpMenu( "" );
-    fAudio1Field = new BMenuField( r, NULL, "Audio 1 :",
-                                     fAudio1PopUp, true );
-    fBox->AddChild( fAudio1Field );
-
-    /* Audio 2 */
-    r = BRect( 10, 105, fBox->Bounds().Width() - 10, 125 );
-    fAudio2PopUp = new BPopUpMenu( "" );
-    fAudio2Field = new BMenuField( r, NULL, "Audio 2 :",
-                                     fAudio2PopUp, true );
-    fBox->AddChild( fAudio2Field );
-
-    /* Video bitrate */
-    r = BRect( 10, 135, fBox->Bounds().Width() - 10, 165 );
-    fVideoSlider = new BSlider( r, NULL, "Video bitrate : 1024 kbps",
-                                new BMessage( SLIDER_VIDEO ),
-                                128, 4096, B_TRIANGLE_THUMB );
-    fVideoSlider->SetValue( 1024 );
-    fBox->AddChild( fVideoSlider );
-
-    /* Audio bitrate */
-    r = BRect( 10, 175, fBox->Bounds().Width() - 10, 205 );
-    fAudioSlider = new BSlider( r, NULL, "Audio bitrate : 128 kbps",
-                                new BMessage( SLIDER_AUDIO ),
-                                64, 384, B_TRIANGLE_THUMB );
-    fAudioSlider->SetValue( 128 );
-    fBox->AddChild( fAudioSlider );
-
-    /* Destination file */
-    r = BRect( 10, 215, fBox->Bounds().Width() - 10, 230 );
-    fFileString = new BStringView( r, NULL, "Destination file :" );
-    fBox->AddChild( fFileString );
-    r = BRect( 10, 235, fBox->Bounds().Width() - 90, 255 );
-    fFileControl = new BTextControl( r, NULL, "", DEFAULT_FILE,
-                                     new BMessage() );
-    fFileControl->SetDivider( 0 );
-    fBox->AddChild( fFileControl );
-    r = BRect( fBox->Bounds().Width() - 80, 230,
-               fBox->Bounds().Width() - 10, 255 );
-    fFileButton = new BButton( r, NULL, "Browse...",
-                               new BMessage( BUTTON_FILE ) );
-    fBox->AddChild( fFileButton );
-
-    /* Settings buttons */
-    r = BRect( fBox->Bounds().Width() - 200, 275,
-               fBox->Bounds().Width() - 100, 300 );
-    fPictureButton = new BButton( r, NULL, "Picture settings...",
-                                  new BMessage( BUTTON_PICTURE ) );
-    fBox->AddChild( fPictureButton );
-
-    r = BRect( fBox->Bounds().Width() - 90, 275,
-               fBox->Bounds().Width() - 10, 300 );
-    fAdvancedButton = new BButton( r, NULL, "Advanced...",
-                                   new BMessage( BUTTON_ADVANCED ) );
-    fBox->AddChild( fAdvancedButton );
-
-    view->AddChild( fBox );
-
-    /* Status bar */
-    r = BRect( 10, view->Bounds().Height() - 75,
-               view->Bounds().Width() - 10, view->Bounds().Height() - 45 );
-    fStatusBar = new BStatusBar( r, NULL, NULL );
-    fStatusBar->SetMaxValue( 1.0 );
-    view->AddChild( fStatusBar );
-
-    /* Buttons */
-    r = BRect( view->Bounds().Width() - 240, view->Bounds().Height() - 35,
-               view->Bounds().Width() - 170, view->Bounds().Height() - 10 );
-    BButton * aboutButton;
-    aboutButton = new BButton( r, NULL, "About...",
-                               new BMessage( B_ABOUT_REQUESTED ) );
-    view->AddChild( aboutButton );
-
-    r = BRect( view->Bounds().Width() - 160, view->Bounds().Height() - 35,
-               view->Bounds().Width() - 90, view->Bounds().Height() - 10 );
-    fSuspendButton = new BButton( r, NULL, "Suspend",
-                                  new BMessage( BUTTON_SUSPEND ) );
-    view->AddChild( fSuspendButton );
-
-    r = BRect( view->Bounds().Width() - 80, view->Bounds().Height() - 35,
-               view->Bounds().Width() - 10, view->Bounds().Height() - 10 );
-    fStartButton = new BButton( r, NULL, "Start !",
-                                new BMessage( BUTTON_START ) );
-    view->AddChild( fStartButton );
-
-    AddChild( view );
-
-    /* -- GUI ends here -- */
-
     /* Init libhb & launch the manager thread */
-    fManager = new HBManager( debug );
+    fManager = new HBManager( true );
 
-    /* Detects DVD drives & VOB folders, then tell libhb to scan it */
-    ScanVolumes();
+    /* Add the scan view */
+    fScanView = new ScanView( fManager );
+    fRipView  = new RipView( fManager );
+    AddChild( fScanView );
+
+    /* Resize to fit */
+    ResizeTo( fScanView->Bounds().Width(), fScanView->Bounds().Height() );
+    
+    BScreen screen;
+    MoveTo( ( screen.Frame().Width() - fRipView->Bounds().Width() ) / 2,
+            ( screen.Frame().Height() - fRipView->Bounds().Height() ) / 2 );
 
     /* Update the interface */
+    fDie = false;
     fUpdateThread = spawn_thread( (int32 (*)(void *)) UpdateInterface,
                                   "interface", B_DISPLAY_PRIORITY, this );
     resume_thread( fUpdateThread );
 }
 
-bool HBWindow::QuitRequested()
+bool MainWindow::QuitRequested()
 {
     /* Clean up */
-    kill_thread( fUpdateThread );
+    fDie = true;
+    long exit_value;
+    wait_for_thread( fUpdateThread, &exit_value );
     delete fManager;
 
     /* Stop the application */
@@ -250,7 +52,7 @@ bool HBWindow::QuitRequested()
     return true;
 }
 
-void HBWindow::MessageReceived( BMessage * message )
+void MainWindow::MessageReceived( BMessage * message )
 {
     switch( message->what )
     {
@@ -269,209 +71,44 @@ void HBWindow::MessageReceived( BMessage * message )
             break;
         }
 
-        case BUTTON_ADVANCED:
-            break;
-
-        case BUTTON_FILE:
-            break;
-
-        case BUTTON_PICTURE:
-        {
-            HBTitle * title =
-                ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle;
-            HBPictureWin * pictureWin = new HBPictureWin( fManager, title );
-            pictureWin->Show();
+        case B_REFS_RECEIVED:
+        case SCAN_RADIO:
+        case SCAN_BROWSE_BUTTON:
+        case SCAN_OPEN:
+            fScanView->MessageReceived( message );
             break;
-        }
-
-        case BUTTON_START:
-        {
-            HBTitle * title =
-                ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle;
-            HBAudio * audio1 =
-                ((HBAudioItem*) fAudio1PopUp->FindMarked())->fAudio;
-            HBAudio * audio2 =
-                ((HBAudioItem*) fAudio2PopUp->FindMarked())->fAudio;
-
-            title->fBitrate = fVideoSlider->Value();
-            if( audio1 )
-            {
-                audio1->fOutBitrate = fAudioSlider->Value();
-            }
-            if( audio2 )
-            {
-                audio2->fOutBitrate = fAudioSlider->Value();
-            }
 
-            fManager->StartRip( title, audio1, audio2,
-                                (char*) fFileControl->Text() );
+        case B_SAVE_REQUESTED:
+        case RIP_TITLE_POPUP:
+        case RIP_BITRATE_RADIO:
+        case RIP_TARGET_CONTROL:
+        case RIP_CROP_BUTTON:
+        case RIP_BROWSE_BUTTON:
+        case RIP_SUSPEND_BUTTON:
+        case RIP_RIP_BUTTON:
+            fRipView->MessageReceived( message );
             break;
-        }
-
-        case BUTTON_CANCEL:
-            fManager->StopRip();
-            break;
-
-        case BUTTON_SUSPEND:
-            fManager->SuspendRip();
-            break;
-
-        case BUTTON_RESUME:
-            fManager->ResumeRip();
-            break;
-
-        case POPUP_AUDIO:
-            break;
-
-        case POPUP_TITLE:
-        {
-            HBTitle * title =
-                ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle;
-
-            /* Empty audio popups */
-            HBAudioItem * audioItem;
-            while( ( audioItem = (HBAudioItem*) fAudio1PopUp->ItemAt( 0 ) ) )
-            {
-                fAudio1PopUp->RemoveItem( audioItem );
-                delete audioItem;
-            }
-            while( ( audioItem = (HBAudioItem*) fAudio2PopUp->ItemAt( 0 ) ) )
-            {
-                fAudio2PopUp->RemoveItem( audioItem );
-                delete audioItem;
-            }
-
-            HBAudio * audio;
-            for( uint32_t i = 0;
-                 i < title->fAudioList->CountItems();
-                 i++ )
-            {
-                audio = (HBAudio*) title->fAudioList->ItemAt( i );
-                fAudio1PopUp->AddItem( new HBAudioItem( audio ) );
-                fAudio2PopUp->AddItem( new HBAudioItem( audio ) );
-            }
-            fAudio1PopUp->AddItem( new HBAudioItem( NULL ) );
-            fAudio2PopUp->AddItem( new HBAudioItem( NULL ) );
-            ((HBAudioItem*) fAudio1PopUp->ItemAt( 0 ))->SetMarked( true );
-            ((HBAudioItem*) fAudio2PopUp->ItemAt(
-                fAudio2PopUp->CountItems() - 1 ))->SetMarked( true );
-
-            break;
-        }
-
-        case POPUP_VOLUME:
-            break;
-
-        case SLIDER_AUDIO:
-        {
-            char label[64]; memset( label, 0, 64 );
-            snprintf( label, 128, "Audio bitrate : %ld kbps",
-                      fAudioSlider->Value() );
-            fAudioSlider->SetLabel( label );
-            break;
-        }
-
-        case SLIDER_VIDEO:
-        {
-            char label[64]; memset( label, 0, 64 );
-            snprintf( label, 128, "Video bitrate : %ld kbps",
-                      fVideoSlider->Value() );
-            fVideoSlider->SetLabel( label );
-            break;
-        }
-
+            
         default:
             BWindow::MessageReceived( message );
             break;
     }
 }
 
-
-void HBWindow::ScanVolumes()
+void MainWindow::UpdateInterface( MainWindow * _this )
 {
-    BVolumeRoster   * roster  = new BVolumeRoster();
-    BVolume         * bVolume = new BVolume();
-    fs_info           info;
-    int               device;
-    device_geometry   geometry;
-
-    HBVolume * volume;
-    HBList   * volumeList = new HBList();
+    uint64_t time;
 
-    /* Parse mounted volumes */
-    while( roster->GetNextVolume( bVolume ) == B_NO_ERROR )
-    {
-        /* open() and ioctl() for more informations */
-        fs_stat_dev( bVolume->Device(), &info );
-        if( ( device = open( info.device_name, O_RDONLY ) ) < 0 )
-        {
-            continue;
-        }
-
-        if( ioctl( device, B_GET_GEOMETRY, &geometry,
-                   sizeof( geometry ) ) < 0 )
-
-        {
-            continue;
-        }
-
-        /* Get the volume name */
-        char volumeName[B_FILE_NAME_LENGTH];
-        bVolume->GetName( volumeName );
-
-        if( bVolume->IsReadOnly() && geometry.device_type == B_CD )
-        {
-            /* May be a DVD */
-            volume = new HBVolume( info.device_name, volumeName );
-            volumeList->AddItem( volume );
-        }
-        else if( geometry.device_type == B_DISK )
-        {
-            /* May be a hard drive. Look for VIDEO_TS folders on it */
-            BQuery * query = new BQuery();
-
-            if( query->SetVolume( bVolume ) != B_OK )
-            {
-                delete query;
-                continue;
-            }
-
-            if( query->SetPredicate( "name = VIDEO_TS.BUP" ) != B_OK )
-            {
-                delete query;
-                continue;
-            }
-
-            query->Fetch();
-
-            BEntry entry, parentEntry;
-            BPath  path;
-            while( query->GetNextEntry( &entry ) == B_OK )
-            {
-                entry.GetParent( &parentEntry );
-                parentEntry.GetPath( &path );
-
-                volume = new HBVolume( (char*) path.Path() );
-                volumeList->AddItem( volume );
-            }
-
-            delete query;
-        }
-    }
-
-    fManager->ScanVolumes( volumeList );
-}
-
-void HBWindow::UpdateInterface( HBWindow * _this )
-{
-    for( ;; )
+    while( !_this->fDie )
     {
+        /* Update every 0.1 sec */
+        time = system_time();
         _this->_UpdateInterface();
-        snooze( 10000 );
+        snooze( 100000 - ( system_time() - time ) );
     }
 }
 
-void HBWindow::_UpdateInterface()
+void MainWindow::_UpdateInterface()
 {
     if( !fManager->NeedUpdate() )
     {
@@ -486,97 +123,31 @@ void HBWindow::_UpdateInterface()
         return;
     }
 
-    EnableInterface( status.fMode );
-
     switch( status.fMode )
     {
         case HB_MODE_UNDEF:
+        case HB_MODE_NEED_VOLUME:
             break;
-
+        
         case HB_MODE_SCANNING:
-        {
-            char text[1024]; memset( text, 0, 1024 );
-            sprintf( text, "Scanning %s, title %d...",
-                     status.fScannedVolume, status.fScannedTitle );
-            fStatusBar->Update( - fStatusBar->CurrentValue(), text );
+        case HB_MODE_INVALID_VOLUME:
+            fScanView->UpdateIntf( status );
             break;
-        }
 
-        case HB_MODE_SCANDONE:
-        {
-            HBVolume * volume;
-            for( uint32_t i = 0;
-                 i < status.fVolumeList->CountItems();
-                 i++ )
-            {
-                volume = (HBVolume*) status.fVolumeList->ItemAt( i );
-                fVolumePopUp->AddItem( new HBVolumeItem( volume ) );
-            }
-            ((HBVolumeItem*) fVolumePopUp->ItemAt( 0 ))->SetMarked( true );
-
-            HBTitle * title;
-            volume = (HBVolume*) status.fVolumeList->ItemAt( 0 );
-            for( uint32_t i = 0;
-                 i < volume->fTitleList->CountItems();
-                 i++ )
-            {
-                title = (HBTitle*) volume->fTitleList->ItemAt( i );
-                fTitlePopUp->AddItem( new HBTitleItem( title ) );
-            }
-            ((HBTitleItem*) fTitlePopUp->ItemAt( 0 ))->SetMarked( true );
-
-            HBAudio * audio;
-            title = (HBTitle*) volume->fTitleList->ItemAt( 0 );
-            for( uint32_t i = 0;
-                 i < title->fAudioList->CountItems();
-                 i++ )
-            {
-                audio = (HBAudio*) title->fAudioList->ItemAt( i );
-                fAudio1PopUp->AddItem( new HBAudioItem( audio ) );
-                fAudio2PopUp->AddItem( new HBAudioItem( audio ) );
-            }
-            fAudio1PopUp->AddItem( new HBAudioItem( NULL ) );
-            fAudio2PopUp->AddItem( new HBAudioItem( NULL ) );
-            ((HBAudioItem*) fAudio1PopUp->ItemAt( 0 ))->SetMarked( true );
-            ((HBAudioItem*) fAudio2PopUp->ItemAt(
-                fAudio2PopUp->CountItems() - 1 ))->SetMarked( true );
-
-            fStatusBar->Update( - fStatusBar->CurrentValue(),
-                                "Ready. Press 'Start' to rip." );
+        case HB_MODE_READY_TO_RIP:
+            RemoveChild( fScanView );
+            ResizeTo( fRipView->Bounds().Width(),
+                      fRipView->Bounds().Height() );
+            AddChild( fRipView );
+            fRipView->UpdateIntf( status );
             break;
-        }
 
         case HB_MODE_ENCODING:
-        {
-            char text[1024]; memset( text, 0, 1024 );
-            sprintf( text,
-                     "Encoding : %.2f %%, %.2f fps (%02d:%02d:%02d remaining)",
-                     100 * status.fPosition, status.fFrameRate,
-                     status.fRemainingTime / 3600,
-                     ( status.fRemainingTime % 3600 ) / 60,
-                     status.fRemainingTime % 60 );
-            fStatusBar->Update( status.fPosition -
-                                fStatusBar->CurrentValue(), text );
-            break;
-        }
-
         case HB_MODE_SUSPENDED:
-        {
-            char text[1024]; memset( text, 0, 1024 );
-            sprintf( text, "Encoding : %.2f %%, %.2f fps (Paused)",
-                     100 * status.fPosition, status.fFrameRate );
-            fStatusBar->Update( status.fPosition -
-                                fStatusBar->CurrentValue(), text );
-            break;
-        }
-
         case HB_MODE_DONE:
-            break;
-
         case HB_MODE_CANCELED:
-            break;
-
         case HB_MODE_ERROR:
+            fRipView->UpdateIntf( status );
             break;
 
         default:
@@ -586,174 +157,3 @@ void HBWindow::_UpdateInterface()
     Unlock();
 }
 
-void HBWindow::EnableInterface( HBMode mode )
-{
-    if( mode == fOldMode && mode != HB_MODE_UNDEF )
-    {
-        return;
-    }
-
-    switch( mode )
-    {
-        case HB_MODE_UNDEF:
-        {
-            fAdvancedButton->SetEnabled( false );
-            fFileButton->SetEnabled( false );
-            fPictureButton->SetEnabled( false );
-            fStartButton->SetEnabled( false );
-            fSuspendButton->SetEnabled( false );
-            fAudio1Field->SetEnabled( false );
-            fAudio2Field->SetEnabled( false );
-            fTitleField->SetEnabled( false );
-            fVolumeField->SetEnabled( false );
-            fAudioSlider->SetEnabled( false );
-            fVideoSlider->SetEnabled( false );
-            fFileString->SetHighColor( 156, 156, 156 );
-            fFileString->Invalidate();
-            fFileControl->SetEnabled( false );
-            break;
-        }
-
-        case HB_MODE_SCANNING:
-        {
-            fAdvancedButton->SetEnabled( true );
-            fFileButton->SetEnabled( true );
-            fPictureButton->SetEnabled( false );
-            fStartButton->SetEnabled( false );
-            fSuspendButton->SetEnabled( false );
-            fAudio1Field->SetEnabled( false );
-            fAudio2Field->SetEnabled( false );
-            fTitleField->SetEnabled( false );
-            fVolumeField->SetEnabled( false );
-            fAudioSlider->SetEnabled( true );
-            fVideoSlider->SetEnabled( true );
-            fFileString->SetHighColor( 0, 0, 0 );
-            fFileString->Invalidate();
-            fFileControl->SetEnabled( true );
-            break;
-        }
-
-        case HB_MODE_SCANDONE:
-        {
-            fAdvancedButton->SetEnabled( true );
-            fFileButton->SetEnabled( true );
-            fPictureButton->SetEnabled( true );
-            fStartButton->SetLabel( "Start" );
-            fStartButton->SetMessage( new BMessage( BUTTON_START ) );
-            fStartButton->SetEnabled( true );
-            fSuspendButton->SetEnabled( false );
-            fAudio1Field->SetEnabled( true );
-            fAudio2Field->SetEnabled( true );
-            fTitleField->SetEnabled( true );
-            fVolumeField->SetEnabled( true );
-            fAudioSlider->SetEnabled( true );
-            fVideoSlider->SetEnabled( true );
-            fFileString->SetHighColor( 0, 0, 0 );
-            fFileString->Invalidate();
-            fFileControl->SetEnabled( true );
-            break;
-        }
-
-        case HB_MODE_ENCODING:
-        {
-            fFileButton->SetEnabled( false );
-            fPictureButton->SetEnabled( false );
-            fStartButton->SetLabel( "Cancel" );
-            fStartButton->SetMessage( new BMessage( BUTTON_CANCEL ) );
-            fStartButton->SetEnabled( true );
-            fSuspendButton->SetLabel( "Suspend" );
-            fSuspendButton->SetMessage( new BMessage( BUTTON_SUSPEND ) );
-            fSuspendButton->SetEnabled( true );
-            fAudio1Field->SetEnabled( false );
-            fAudio2Field->SetEnabled( false );
-            fTitleField->SetEnabled( false );
-            fVolumeField->SetEnabled( false );
-            fAudioSlider->SetEnabled( false );
-            fVideoSlider->SetEnabled( false );
-            fFileString->SetHighColor( 156, 156, 156 );
-            fFileString->Invalidate();
-            fFileControl->SetEnabled( false );
-            break;
-        }
-
-        case HB_MODE_SUSPENDED:
-        {
-            fFileButton->SetEnabled( false );
-            fPictureButton->SetEnabled( false );
-            fStartButton->SetLabel( "Cancel" );
-            fStartButton->SetMessage( new BMessage( BUTTON_CANCEL ) );
-            fStartButton->SetEnabled( true );
-            fSuspendButton->SetLabel( "Resume" );
-            fSuspendButton->SetMessage( new BMessage( BUTTON_RESUME ) );
-            fSuspendButton->SetEnabled( true );
-            fAudio1Field->SetEnabled( false );
-            fAudio2Field->SetEnabled( false );
-            fTitleField->SetEnabled( false );
-            fVolumeField->SetEnabled( false );
-            fAudioSlider->SetEnabled( false );
-            fVideoSlider->SetEnabled( false );
-            fFileString->SetHighColor( 156, 156, 156 );
-            fFileString->Invalidate();
-            fFileControl->SetEnabled( false );
-            break;
-        }
-
-        case HB_MODE_DONE:
-        {
-            fFileButton->SetEnabled( false );
-            fPictureButton->SetEnabled( false );
-            fStartButton->SetEnabled( true );
-            fSuspendButton->SetEnabled( true );
-            fAudio1Field->SetEnabled( false );
-            fAudio2Field->SetEnabled( false );
-            fTitleField->SetEnabled( false );
-            fVolumeField->SetEnabled( false );
-            fAudioSlider->SetEnabled( false );
-            fVideoSlider->SetEnabled( false );
-            fFileString->SetHighColor( 156, 156, 156 );
-            fFileString->Invalidate();
-            fFileControl->SetEnabled( false );
-            break;
-        }
-
-        case HB_MODE_CANCELED:
-        {
-            fFileButton->SetEnabled( false );
-            fPictureButton->SetEnabled( false );
-            fStartButton->SetEnabled( true );
-            fSuspendButton->SetEnabled( true );
-            fAudio1Field->SetEnabled( false );
-            fAudio2Field->SetEnabled( false );
-            fTitleField->SetEnabled( false );
-            fVolumeField->SetEnabled( false );
-            fAudioSlider->SetEnabled( false );
-            fVideoSlider->SetEnabled( false );
-            fFileString->SetHighColor( 156, 156, 156 );
-            fFileString->Invalidate();
-            fFileControl->SetEnabled( false );
-            break;
-        }
-
-        case HB_MODE_ERROR:
-        {
-            fFileButton->SetEnabled( false );
-            fPictureButton->SetEnabled( false );
-            fStartButton->SetEnabled( true );
-            fSuspendButton->SetEnabled( true );
-            fAudio1Field->SetEnabled( false );
-            fAudio2Field->SetEnabled( false );
-            fTitleField->SetEnabled( false );
-            fVolumeField->SetEnabled( false );
-            fAudioSlider->SetEnabled( false );
-            fVideoSlider->SetEnabled( false );
-            fFileString->SetHighColor( 156, 156, 156 );
-            fFileString->Invalidate();
-            fFileControl->SetEnabled( false );
-            break;
-        }
-
-        default:
-            break;
-    }
-}
-
index e40c258..c4c32a7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: MainWindow.h,v 1.9 2003/09/30 14:38:15 titer Exp $
+/* $Id: MainWindow.h,v 1.10 2003/10/10 01:08:42 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -8,93 +8,29 @@
 #ifndef HB_MAIN_WINDOW_H
 #define HB_MAIN_WINDOW_H
 
-/* BeOS headers */
-#include <Box.h>
-#include <MenuItem.h>
 #include <Window.h>
-class BButton;
-class BMenuField;
-class BPopUpMenu;
-class BSlider;
-class BStatusBar;
-class BStringView;
-class BTextControl;
+class ScanView;
+class RipView;
 
-/* libhb headers */
-#include "Manager.h"
+#include "Common.h"
 
-class HBVolumeItem : public BMenuItem
+class MainWindow : public BWindow
 {
     public:
-                   HBVolumeItem( HBVolume * volume );
-
-        HBVolume * fVolume;
-};
-
-class HBTitleItem : public BMenuItem
-{
-    public:
-                  HBTitleItem( HBTitle * title );
-
-        HBTitle * fTitle;
-};
-
-class HBAudioItem : public BMenuItem
-{
-    public:
-                  HBAudioItem( HBAudio * audio );
-
-        HBAudio * fAudio;
-};
-
-class HBBox : public BBox
-{
-    public:
-             HBBox( BRect );
-        void Draw( BRect );
-};
-
-class HBWindow : public BWindow
-{
-    public:
-                        HBWindow( bool debug );
+                        MainWindow();
         virtual bool    QuitRequested();
         virtual void    MessageReceived( BMessage * message );
 
-        void            ScanVolumes();
-
     private:
-        static void     UpdateInterface( HBWindow * _this );
+        static void     UpdateInterface( MainWindow * _this );
         void            _UpdateInterface();
-        void            EnableInterface( HBMode mode );
 
         HBManager     * fManager;
-
-        /* GUI */
-        HBBox         * fBox;
-        BButton       * fAdvancedButton;
-        BButton       * fFileButton;
-        BButton       * fPictureButton;
-        BButton       * fStartButton;
-        BButton       * fSuspendButton;
-        BMenuField    * fAudio1Field;
-        BMenuField    * fAudio2Field;
-        BMenuField    * fTitleField;
-        BMenuField    * fVolumeField;
-        BPopUpMenu    * fAudio1PopUp;
-        BPopUpMenu    * fAudio2PopUp;
-        BPopUpMenu    * fTitlePopUp;
-        BPopUpMenu    * fVolumePopUp;
-        BSlider       * fAudioSlider;
-        BSlider       * fVideoSlider;
-        BStatusBar    * fStatusBar;
-        BStringView   * fFileString;
-        BTextControl  * fFileControl;
-
         int             fUpdateThread;
+        volatile bool   fDie;
 
-        /* Used to SetEnabled() GUI items only if needed */
-        HBMode          fOldMode;
+        ScanView      * fScanView;
+        RipView       * fRipView;
 };
 
 #endif
diff --git a/beos/RipView.cpp b/beos/RipView.cpp
new file mode 100644 (file)
index 0000000..180ba23
--- /dev/null
@@ -0,0 +1,616 @@
+/* $Id: RipView.cpp,v 1.6 2003/10/13 23:42:03 titer Exp $
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://beos.titer.org/handbrake/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#include <Box.h>
+#include <Button.h>
+#include <CheckBox.h>
+#include <FilePanel.h>
+#include <MenuField.h>
+#include <MenuItem.h>
+#include <Path.h>
+#include <PopUpMenu.h>
+#include <RadioButton.h>
+#include <StatusBar.h>
+#include <String.h>
+#include <TextControl.h>
+
+#include "RipView.h"
+#include "PictureWin.h"
+#include "Manager.h"
+
+#define DEFAULT_FILE "/boot/home/Desktop/Movie.avi"
+
+RipView::RipView( HBManager * manager )
+    : BView( BRect( 0,0,400,480 ), NULL, B_FOLLOW_ALL, B_WILL_DRAW )
+{
+    fManager = manager;
+    
+    BRect r;
+    SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
+    
+    /* Video box */
+    r = BRect( 10, 10, Bounds().Width() - 10, 160 );
+    fVideoBox = new BBox( r );
+    fVideoBox->SetLabel( "Video" );
+    AddChild( fVideoBox );
+
+    /* Title */
+    r = BRect( 10, 15, fVideoBox->Bounds().Width() - 10, 35 );
+    fTitlePopUp = new BPopUpMenu( "" );
+    fTitleField = new BMenuField( r, NULL, "Title:",
+                                  fTitlePopUp, true );
+    fVideoBox->AddChild( fTitleField );
+
+    /* Video codec */
+    r = BRect( 10, 40, fVideoBox->Bounds().Width() - 10, 60 );
+    fVideoCodecPopUp = new BPopUpMenu( "" );
+    fVideoCodecField = new BMenuField( r, NULL, "Codec:",
+                                       fVideoCodecPopUp, true );
+    fVideoBox->AddChild( fVideoCodecField );
+
+    /* Video bitrate */
+    r = BRect( 10, 65, fVideoBox->Bounds().Width() / 2, 85 );
+    fCustomBitrateRadio =
+        new BRadioButton( r, NULL, "Custom bitrate (kbps)",
+                          new BMessage( RIP_BITRATE_RADIO ) );
+    fCustomBitrateRadio->SetValue( 1 );
+    fVideoBox->AddChild( fCustomBitrateRadio );
+    r = BRect( fVideoBox->Bounds().Width() - 80, 65,
+               fVideoBox->Bounds().Width() - 10, 85 );
+    fCustomBitrateControl = new BTextControl( r, NULL, NULL, "1024", NULL );
+    fCustomBitrateControl->SetDivider( 0 );
+    fVideoBox->AddChild( fCustomBitrateControl );
+    r = BRect( 10, 90, fVideoBox->Bounds().Width() / 2, 110 );
+    fTargetSizeRadio =
+        new BRadioButton( r, NULL, "Target size (MB)",
+                          new BMessage( RIP_BITRATE_RADIO ) );
+    fVideoBox->AddChild( fTargetSizeRadio );
+    r = BRect( fVideoBox->Bounds().Width() - 80, 90,
+               fVideoBox->Bounds().Width() - 10, 110 );
+    fTargetSizeControl = new BTextControl( r, NULL, NULL, "700", NULL );
+    fTargetSizeControl->SetDivider( 0 );
+    fTargetSizeControl->SetEnabled( false );
+    fTargetSizeControl->SetModificationMessage(
+        new BMessage( RIP_TARGET_CONTROL ) );
+    fVideoBox->AddChild( fTargetSizeControl );
+
+    /* 2-pass */
+    r = BRect( 10, 125, fVideoBox->Bounds().Width() / 2, 140 );
+    fTwoPassCheck = new BCheckBox( r, NULL, "2-pass encoding", NULL );
+    fVideoBox->AddChild( fTwoPassCheck );
+
+    /* Crop */
+    r = BRect( fVideoBox->Bounds().Width() - 120, 120,
+               fVideoBox->Bounds().Width() - 10, 140 );
+    fCropButton = new BButton( r, NULL, "Crop & Resize...",
+                               new BMessage( RIP_CROP_BUTTON ) );
+    fVideoBox->AddChild( fCropButton );
+
+    /* Audio box */
+    r = BRect( 10, 170, Bounds().Width() - 10, 290 );
+    fAudioBox = new BBox( r );
+    fAudioBox->SetLabel( "Audio" );
+    AddChild( fAudioBox );
+
+    /* Language */
+    r = BRect( 10, 15, fAudioBox->Bounds().Width() - 10, 35 );
+    fLanguagePopUp = new BPopUpMenu( "" );
+    fLanguageField = new BMenuField( r, NULL, "Language:",
+                                     fLanguagePopUp, true );
+    fAudioBox->AddChild( fLanguageField );
+
+    /* Secondary language */
+    r = BRect( 10, 40, fAudioBox->Bounds().Width() - 10, 60 );
+    fSecondaryLanguagePopUp = new BPopUpMenu( "" );
+    fSecondaryLanguageField = new BMenuField( r, NULL, "Secondary language:",
+                                              fSecondaryLanguagePopUp, true );
+    fAudioBox->AddChild( fSecondaryLanguageField );
+
+    /* Audio codec */
+    r = BRect( 10, 65, fAudioBox->Bounds().Width() - 10, 85 );
+    fAudioCodecPopUp = new BPopUpMenu( "" );
+    fAudioCodecField = new BMenuField( r, NULL, "Codec:",
+                                       fAudioCodecPopUp, true );
+    fAudioBox->AddChild( fAudioCodecField );
+
+    /* Audio bitrate */
+    r = BRect( 10, 90, fAudioBox->Bounds().Width() - 10, 110 );
+    fAudioBitratePopUp = new BPopUpMenu( "" );
+    fAudioBitrateField = new BMenuField( r, NULL, "Bitrate:",
+                                         fAudioBitratePopUp, true );
+    fAudioBox->AddChild( fAudioBitrateField );
+
+    /* Destination box */
+    r = BRect( 10, 300, Bounds().Width() - 10, 395 );
+    fDestinationBox = new BBox( r );
+    fDestinationBox->SetLabel( "Destination" );
+    AddChild( fDestinationBox );
+
+    /* File format */
+    r = BRect( 10, 15, fDestinationBox->Bounds().Width() - 10, 35 );
+    fFileFormatPopUp = new BPopUpMenu( "" );
+    fFileFormatField = new BMenuField( r, NULL, "File format:",
+                                       fFileFormatPopUp, true );
+    fDestinationBox->AddChild( fFileFormatField );
+
+    /* File location */
+    r = BRect( 10, 40, fDestinationBox->Bounds().Width() - 10, 60 );
+    fFileControl = new BTextControl( r, NULL, "Location:",
+                                     DEFAULT_FILE, NULL );
+    fFileControl->SetDivider( 100 );
+    fDestinationBox->AddChild( fFileControl );
+
+    /* Browse button */
+    r = BRect( fDestinationBox->Bounds().Width() - 80, 65,
+               fDestinationBox->Bounds().Width() - 10, 85 );
+    fFileButton = new BButton( r, NULL, "Browse...",
+                               new BMessage( RIP_BROWSE_BUTTON ) );
+    fDestinationBox->AddChild( fFileButton );
+
+    fFilePanel = new BFilePanel( B_SAVE_PANEL, NULL, NULL, 0, false );
+
+    /* Status bar */
+    r = BRect( 10, 405, Bounds().Width() - 10, 435 );
+    fStatusBar = new BStatusBar( r, NULL );
+    AddChild( fStatusBar );
+
+    /* Suspend/Rip buttons */
+    r = BRect( Bounds().Width() - 180, 445,
+               Bounds().Width() - 100, 465 );
+    fSuspendButton = new BButton( r, NULL, "Suspend",
+                                  new BMessage( RIP_SUSPEND_BUTTON ) );
+    fSuspendButton->SetEnabled( false );
+    AddChild( fSuspendButton );
+    r = BRect( Bounds().Width() - 90, 445,
+               Bounds().Width() - 10, 465 );
+    fStartButton = new BButton( r, NULL, "Rip !",
+                                new BMessage( RIP_RIP_BUTTON ) );
+    fStartButton->MakeDefault( true );
+    AddChild( fStartButton );
+
+    /* Fill popups */
+    fVideoCodecPopUp->AddItem( new BMenuItem( "MPEG-4", NULL ) );
+    fVideoCodecPopUp->ItemAt( 0 )->SetMarked( true );
+    fAudioCodecPopUp->AddItem( new BMenuItem( "MP3", NULL ) );
+    fAudioCodecPopUp->ItemAt( 0 )->SetMarked( true );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "32", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "64", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "96", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "128", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "160", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "192", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "224", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "256", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "288", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->AddItem(
+        new BMenuItem( "320", new BMessage( RIP_TARGET_CONTROL ) ) );
+    fAudioBitratePopUp->ItemAt( 3 )->SetMarked( true );
+    fFileFormatPopUp->AddItem( new BMenuItem( "AVI", NULL ) );
+    fFileFormatPopUp->ItemAt( 0 )->SetMarked( true );
+}
+
+void RipView::MessageReceived( BMessage * message )
+{
+    switch( message->what )
+    {
+        case RIP_TITLE_POPUP:
+        {
+            int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() );
+            HBTitle * title = (HBTitle*) fTitleList->ItemAt( index );
+
+            /* Empty current popups */
+            BMenuItem * item;
+            while( ( item = fLanguagePopUp->ItemAt( 0 ) ) )
+            {
+                fLanguagePopUp->RemoveItem( item );
+                delete item;
+            }
+            while( ( item = fSecondaryLanguagePopUp->ItemAt( 0 ) ) )
+            {
+                fSecondaryLanguagePopUp->RemoveItem( item );
+                delete item;
+            }
+
+            /* Show new languages */
+            HBAudio * audio;
+            for( uint32_t i = 0; i < title->fAudioList->CountItems(); i++ )
+            {
+                audio = (HBAudio*) title->fAudioList->ItemAt( i );
+                fLanguagePopUp->AddItem(
+                    new BMenuItem( audio->fDescription, NULL ) );
+                fSecondaryLanguagePopUp->AddItem(
+                    new BMenuItem( audio->fDescription,
+                                   new BMessage( RIP_TARGET_CONTROL ) ) );
+            }
+            fLanguagePopUp->ItemAt( 0 )->SetMarked( true );
+            fSecondaryLanguagePopUp->AddItem( new BMenuItem( "None",
+                new BMessage( RIP_TARGET_CONTROL ) ) );
+            fSecondaryLanguagePopUp->ItemAt(
+                fSecondaryLanguagePopUp->CountItems() - 1 )->SetMarked( true );
+            
+            fSecondaryLanguageField->SetEnabled(
+                ( title->fAudioList->CountItems() > 1 ) );
+            
+            break;
+        }
+
+        case RIP_BITRATE_RADIO:
+        {
+            if( fCustomBitrateRadio->Value() )
+            {
+                fCustomBitrateControl->SetEnabled( true );
+                fTargetSizeControl->SetEnabled( false );
+            }
+            else
+            {
+                fCustomBitrateControl->SetEnabled( false );
+                fTargetSizeControl->SetEnabled( true );
+                Window()->PostMessage( RIP_TARGET_CONTROL );
+            }
+            break;
+        }
+
+        case RIP_TARGET_CONTROL:
+        {
+            if( !fTargetSizeRadio->Value() )
+            {
+                break;
+            }
+            
+            int64_t available;
+            int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() );
+            HBTitle * title = (HBTitle*) fTitleList->ItemAt( index );
+            
+            available  = (int64_t) 1024 * 1024 *
+                             atoi( fTargetSizeControl->Text() );
+            
+            /* AVI headers */
+            available -= 2048;
+
+            /* Video chunk headers (8 bytes / frame) and
+               and index (16 bytes / frame) */
+            available -= 24 * title->fLength * title->fRate /
+                             title->fScale;
+            
+            /* Audio tracks */
+            available -=
+                ( strcmp( fSecondaryLanguagePopUp->FindMarked()->Label(),
+                          "None" ) ? 2 : 1 ) *
+                ( title->fLength *
+                  atoi( fAudioBitratePopUp->FindMarked()->Label() ) * 128 +
+                  24 * title->fLength * 44100 / 1152 );
+            
+            char string[1024]; memset( string, 0, 1024 );
+            if( available < 0 )
+            {
+                sprintf( string, "0" );
+            }
+            else
+            {
+                sprintf( string, "%lld", available /
+                         ( 128 * title->fLength ) );
+            }
+            fCustomBitrateControl->SetText( string );
+            break;
+        }
+
+        case RIP_CROP_BUTTON:
+        {
+            int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() );
+            HBTitle * title = (HBTitle*) fTitleList->ItemAt( index );
+
+            HBPictureWin * win;
+            win = new HBPictureWin( fManager, title );
+            win->Show();
+            break;
+        }
+
+        case RIP_BROWSE_BUTTON:
+        {
+            fFilePanel->Show();
+        }
+
+        case B_SAVE_REQUESTED:
+        {
+            entry_ref ref;
+            BString string;
+            if( message->FindRef( "directory", 0, &ref ) == B_OK &&
+                message->FindString( "name", &string ) == B_OK )
+            {
+                BPath * path = new BPath( &ref );
+                string.Prepend( "/" );
+                string.Prepend( path->Path() );
+                fFileControl->SetText( string.String() );
+            }
+            break;
+        }
+
+        case RIP_SUSPEND_BUTTON:
+        {
+            if( strcmp( fSuspendButton->Label(), "Suspend" ) )
+            {
+                fManager->ResumeRip();
+            }
+            else
+            {
+                fManager->SuspendRip();
+            }
+            
+            break;
+        }
+
+        case RIP_RIP_BUTTON:
+        {
+            if( strcmp( fStartButton->Label(), "Rip !" ) )
+            {
+                fManager->StopRip();
+            }
+            else
+            {
+                int index;
+                
+                /* Get asked title & languages */
+                index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() );
+                HBTitle * title = (HBTitle*) fTitleList->ItemAt( index );
+                index = fLanguagePopUp->IndexOf( fLanguagePopUp->FindMarked() );
+                HBAudio * audio1 =
+                    (HBAudio*) title->fAudioList->ItemAt( index );
+                index = fSecondaryLanguagePopUp->IndexOf(
+                    fSecondaryLanguagePopUp->FindMarked() );
+                HBAudio * audio2 =
+                    (HBAudio*) title->fAudioList->ItemAt( index );
+
+                /* Use user settings */
+                title->fBitrate = atoi( fCustomBitrateControl->Text() );
+                title->fTwoPass = ( fTwoPassCheck->Value() != 0 );
+                audio1->fOutBitrate =
+                    atoi( fAudioBitratePopUp->FindMarked()->Label() );
+                if( audio2 )
+                {
+                    audio2->fOutBitrate =
+                        atoi( fAudioBitratePopUp->FindMarked()->Label() );
+                }
+
+                /* Let libhb do the job */
+                fManager->StartRip( title, audio1, audio2,
+                                    (char*) fFileControl->Text() );
+            }
+            break;
+        }
+
+        default:
+            BView::MessageReceived( message );
+            break;
+    }
+}
+
+void RipView::UpdateIntf( HBStatus status )
+{
+    switch( status.fMode )
+    {
+        case HB_MODE_READY_TO_RIP:
+        {
+            fTitleList = status.fTitleList;
+            
+            HBTitle * title;
+            for( uint32_t i = 0; i < fTitleList->CountItems(); i++ )
+            {
+                title = (HBTitle*) fTitleList->ItemAt( i );
+                char string[1024]; memset( string, 0, 1024 );
+                sprintf( string, "%d (%02lld:%02lld:%02lld)",
+                         title->fIndex, title->fLength / 3600,
+                         ( title->fLength % 3600 ) / 60,
+                         title->fLength % 60 );
+                fTitlePopUp->AddItem(
+                    new BMenuItem( string, new BMessage( RIP_TITLE_POPUP ) ) );
+            }
+            fTitlePopUp->ItemAt( 0 )->SetMarked( true );
+            Window()->PostMessage( RIP_TITLE_POPUP );
+            break;
+        }
+
+        case HB_MODE_ENCODING:
+        {
+            fTitleField->SetEnabled( false );
+            fVideoCodecField->SetEnabled( false );
+            fCustomBitrateRadio->SetEnabled( false );
+            fCustomBitrateControl->SetEnabled( false );
+            fTargetSizeRadio->SetEnabled( false );
+            fTargetSizeControl->SetEnabled( false );
+            fTwoPassCheck->SetEnabled( false );
+            fCropButton->SetEnabled( false );
+            fLanguageField->SetEnabled( false );
+            fSecondaryLanguageField->SetEnabled( false );
+            fAudioCodecField->SetEnabled( false );
+            fAudioBitrateField->SetEnabled( false );
+            fFileFormatField->SetEnabled( false );
+            fFileControl->SetEnabled( false );
+            fFileButton->SetEnabled( false );
+
+            if( !status.fPosition )
+            {
+                fStatusBar->Update( - fStatusBar->CurrentValue(),
+                                    "Starting..." );
+            }
+            else
+            {
+                char string[1024]; memset( string, 0, 1024 );
+                sprintf( string, "Encoding: %.2f %% (%.2f fps, "
+                         "%02d:%02d:%02d remaining)",
+                         100 * status.fPosition,
+                         status.fFrameRate,
+                         status.fRemainingTime / 3600,
+                         ( status.fRemainingTime % 3600 ) / 60,
+                         status.fRemainingTime % 60 );
+                fStatusBar->Update( 100 * status.fPosition -
+                                    fStatusBar->CurrentValue(),
+                                    string );
+            }
+            
+            fSuspendButton->SetLabel( "Suspend" );
+            fSuspendButton->SetEnabled( true );
+            fStartButton->SetLabel( "Cancel" );
+            fStartButton->SetEnabled( true );
+            break;
+        }
+
+        case HB_MODE_SUSPENDED:
+        {
+            fTitleField->SetEnabled( false );
+            fVideoCodecField->SetEnabled( false );
+            fCustomBitrateRadio->SetEnabled( false );
+            fCustomBitrateControl->SetEnabled( false );
+            fTargetSizeRadio->SetEnabled( false );
+            fTargetSizeControl->SetEnabled( false );
+            fTwoPassCheck->SetEnabled( false );
+            fCropButton->SetEnabled( false );
+            fLanguageField->SetEnabled( false );
+            fSecondaryLanguageField->SetEnabled( false );
+            fAudioCodecField->SetEnabled( false );
+            fAudioBitrateField->SetEnabled( false );
+            fFileFormatField->SetEnabled( false );
+            fFileControl->SetEnabled( false );
+            fFileButton->SetEnabled( false );
+
+            fStatusBar->Update( 100 * status.fPosition -
+                                fStatusBar->CurrentValue(), "Suspended" );
+            
+            fSuspendButton->SetLabel( "Resume" );
+            fSuspendButton->SetEnabled( true );
+            fStartButton->SetLabel( "Cancel" );
+            fStartButton->SetEnabled( true );
+            break;
+        }
+
+        case HB_MODE_STOPPING:
+        {
+            fTitleField->SetEnabled( false );
+            fVideoCodecField->SetEnabled( false );
+            fCustomBitrateRadio->SetEnabled( false );
+            fCustomBitrateControl->SetEnabled( false );
+            fTargetSizeRadio->SetEnabled( false );
+            fTargetSizeControl->SetEnabled( false );
+            fTwoPassCheck->SetEnabled( false );
+            fCropButton->SetEnabled( false );
+            fLanguageField->SetEnabled( false );
+            fSecondaryLanguageField->SetEnabled( false );
+            fAudioCodecField->SetEnabled( false );
+            fAudioBitrateField->SetEnabled( false );
+            fFileFormatField->SetEnabled( false );
+            fFileControl->SetEnabled( false );
+            fFileButton->SetEnabled( false );
+
+            fStatusBar->Update( - fStatusBar->CurrentValue(),
+                                "Stopping..." );
+            
+            fSuspendButton->SetLabel( "Suspend" );
+            fSuspendButton->SetEnabled( false );
+            fStartButton->SetLabel( "Cancel" );
+            fStartButton->SetEnabled( false );
+            break;
+        }
+
+        case HB_MODE_DONE:
+        {
+            fTitleField->SetEnabled( true );
+            fVideoCodecField->SetEnabled( true );
+            fCustomBitrateRadio->SetEnabled( true );
+            fCustomBitrateControl->SetEnabled( fCustomBitrateRadio->Value() );
+            fTargetSizeRadio->SetEnabled( true );
+            fTargetSizeControl->SetEnabled( fTargetSizeRadio->Value() );
+            fTwoPassCheck->SetEnabled( true );
+            fCropButton->SetEnabled( true );
+            fLanguageField->SetEnabled( true );
+            fSecondaryLanguageField->SetEnabled(
+                ( fSecondaryLanguagePopUp->CountItems() > 2 ) );
+            fAudioCodecField->SetEnabled( true );
+            fAudioBitrateField->SetEnabled( true );
+            fFileFormatField->SetEnabled( true );
+            fFileControl->SetEnabled( true );
+            fFileButton->SetEnabled( true );
+
+            fStatusBar->Update( 100.0 - fStatusBar->CurrentValue(),
+                                "Done." );
+            
+            fSuspendButton->SetLabel( "Suspend" );
+            fSuspendButton->SetEnabled( false );
+            fStartButton->SetLabel( "Rip !" );
+            fStartButton->SetEnabled( true );
+            break;
+        }
+
+        case HB_MODE_CANCELED:
+        {
+            fTitleField->SetEnabled( true );
+            fVideoCodecField->SetEnabled( true );
+            fCustomBitrateRadio->SetEnabled( true );
+            fCustomBitrateControl->SetEnabled( fCustomBitrateRadio->Value() );
+            fTargetSizeRadio->SetEnabled( true );
+            fTargetSizeControl->SetEnabled( fTargetSizeRadio->Value() );
+            fTwoPassCheck->SetEnabled( true );
+            fCropButton->SetEnabled( true );
+            fLanguageField->SetEnabled( true );
+            fSecondaryLanguageField->SetEnabled(
+                ( fSecondaryLanguagePopUp->CountItems() > 2 ) );
+            fAudioCodecField->SetEnabled( true );
+            fAudioBitrateField->SetEnabled( true );
+            fFileFormatField->SetEnabled( true );
+            fFileControl->SetEnabled( true );
+            fFileButton->SetEnabled( true );
+
+            fStatusBar->Update( - fStatusBar->CurrentValue(),
+                                "Canceled." );
+            
+            fSuspendButton->SetLabel( "Suspend" );
+            fSuspendButton->SetEnabled( false );
+            fStartButton->SetLabel( "Rip !" );
+            fStartButton->SetEnabled( true );
+            break;
+        }
+
+        case HB_MODE_ERROR:
+        {
+            fTitleField->SetEnabled( true );
+            fVideoCodecField->SetEnabled( true );
+            fCustomBitrateRadio->SetEnabled( true );
+            fCustomBitrateControl->SetEnabled( fCustomBitrateRadio->Value() );
+            fTargetSizeRadio->SetEnabled( true );
+            fTargetSizeControl->SetEnabled( fTargetSizeRadio->Value() );
+            fTwoPassCheck->SetEnabled( true );
+            fCropButton->SetEnabled( true );
+            fLanguageField->SetEnabled( true );
+            fSecondaryLanguageField->SetEnabled(
+                ( fSecondaryLanguagePopUp->CountItems() > 2 ) );
+            fAudioCodecField->SetEnabled( true );
+            fAudioBitrateField->SetEnabled( true );
+            fFileFormatField->SetEnabled( true );
+            fFileControl->SetEnabled( true );
+            fFileButton->SetEnabled( true );
+
+            fStatusBar->Update( - fStatusBar->CurrentValue(),
+                                "Error." );
+            
+            fSuspendButton->SetLabel( "Suspend" );
+            fSuspendButton->SetEnabled( false );
+            fStartButton->SetLabel( "Rip !" );
+            fStartButton->SetEnabled( true );
+            break;
+        }
+
+        default:
+            break;
+    }
+}
+
diff --git a/beos/RipView.h b/beos/RipView.h
new file mode 100644 (file)
index 0000000..d487b2b
--- /dev/null
@@ -0,0 +1,77 @@
+/* $Id: RipView.h,v 1.5 2003/10/13 22:23:02 titer Exp $
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://beos.titer.org/handbrake/>.
+   It may be used under the terms of the GNU General Public License. */
+
+
+#ifndef HB_RIP_VIEW_H
+#define HB_RIP_VIEW_H
+
+#include <View.h>
+class BBox;
+class BButton;
+class BCheckBox;
+class BFilePanel;
+class BMenuField;
+class BPopUpMenu;
+class BRadioButton;
+class BStatusBar;
+class BTextControl;
+
+#include "Common.h"
+
+#define RIP_TITLE_POPUP    'rtip'
+#define RIP_BITRATE_RADIO  'rbir'
+#define RIP_TARGET_CONTROL 'rtac'
+#define RIP_CROP_BUTTON    'rcrb'
+#define RIP_BROWSE_BUTTON  'rbrb'
+#define RIP_SUSPEND_BUTTON 'rsub'
+#define RIP_RIP_BUTTON     'rrib'
+
+class RipView : public BView
+{
+    public:
+                       RipView( HBManager * manager );
+        void           MessageReceived( BMessage * message );
+        void           UpdateIntf( HBStatus status );
+
+    private:
+        HBManager    * fManager;
+        HBList       * fTitleList;
+        
+        BBox         * fVideoBox;
+        BPopUpMenu   * fTitlePopUp;
+        BMenuField   * fTitleField;
+        BPopUpMenu   * fVideoCodecPopUp;
+        BMenuField   * fVideoCodecField;
+        BRadioButton * fCustomBitrateRadio;
+        BTextControl * fCustomBitrateControl;
+        BRadioButton * fTargetSizeRadio;
+        BTextControl * fTargetSizeControl;
+        BCheckBox    * fTwoPassCheck;
+        BButton      * fCropButton;
+
+        BBox         * fAudioBox;
+        BPopUpMenu   * fLanguagePopUp;
+        BMenuField   * fLanguageField;
+        BPopUpMenu   * fSecondaryLanguagePopUp;
+        BMenuField   * fSecondaryLanguageField;
+        BPopUpMenu   * fAudioCodecPopUp;
+        BMenuField   * fAudioCodecField;
+        BPopUpMenu   * fAudioBitratePopUp;
+        BMenuField   * fAudioBitrateField;
+
+        BBox         * fDestinationBox;
+        BPopUpMenu   * fFileFormatPopUp;
+        BMenuField   * fFileFormatField;
+        BTextControl * fFileControl;
+        BButton      * fFileButton;
+        BFilePanel   * fFilePanel;
+
+        BStatusBar   * fStatusBar;
+        BButton      * fSuspendButton;
+        BButton      * fStartButton;
+};
+
+#endif
diff --git a/beos/ScanView.cpp b/beos/ScanView.cpp
new file mode 100644 (file)
index 0000000..fb5d722
--- /dev/null
@@ -0,0 +1,280 @@
+/* $Id: ScanView.cpp,v 1.4 2003/10/13 23:42:03 titer Exp $
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://beos.titer.org/handbrake/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#include <fs_info.h>
+#include <sys/ioctl.h>
+#include <Box.h>
+#include <Button.h>
+#include <Directory.h>
+#include <Drivers.h>
+#include <FilePanel.h>
+#include <MenuField.h>
+#include <MenuItem.h>
+#include <Path.h>
+#include <PopUpMenu.h>
+#include <Query.h>
+#include <RadioButton.h>
+#include <StringView.h>
+#include <TextControl.h>
+#include <VolumeRoster.h>
+
+#include "Manager.h"
+#include "ScanView.h"
+
+ScanView::ScanView( HBManager * manager )
+    : BView( BRect( 0,0,400,190 ), NULL, B_FOLLOW_ALL, B_WILL_DRAW )
+{
+    fManager = manager;
+    
+    BRect r;
+    SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
+
+    r = BRect( 10, 10, Bounds().Width() - 10, 115 );
+    BBox * box = new BBox( r );
+    box->SetLabel( "Select source:" );
+    AddChild( box );
+   
+    r = BRect( 10, 15, box->Bounds().Width() / 2, 35 );
+    fRadioDetected = new BRadioButton( r, NULL, "Detected volume:",
+                                       new BMessage( SCAN_RADIO ) );
+    box->AddChild( fRadioDetected );
+    
+    r = BRect( box->Bounds().Width() / 2, 15,
+               box->Bounds().Width() - 10, 35 );
+    fPopUp = new BPopUpMenu( "" );
+    fField = new BMenuField( r, NULL, NULL, fPopUp, true );
+    fField->SetDivider( 0 );
+    box->AddChild( fField );
+
+    r = BRect( 10, 45, box->Bounds().Width() / 3, 65 );
+    fRadioFolder = new BRadioButton( r, NULL, "DVD folder:",
+                                     new BMessage( SCAN_RADIO ) );
+    box->AddChild( fRadioFolder );
+
+    r = BRect( box->Bounds().Width() / 3, 45,
+               box->Bounds().Width() - 10, 65 );
+    fFolderControl = new BTextControl( r, NULL, NULL, NULL, NULL );
+    box->AddChild( fFolderControl );
+    
+    r = BRect( box->Bounds().Width() - 80, 70,
+               box->Bounds().Width() - 10, 95 );
+    fBrowseButton = new BButton( r, NULL, "Browse...",
+                                 new BMessage( SCAN_BROWSE_BUTTON ) );
+    box->AddChild( fBrowseButton );
+
+    fFilePanel = new BFilePanel( B_OPEN_PANEL, NULL,
+                                 NULL, B_DIRECTORY_NODE );
+
+    r = BRect( 10, 125, Bounds().Width() - 10, 145 );
+    fStatusString = new BStringView( r, NULL, NULL );
+    AddChild( fStatusString );
+    
+    r = BRect( Bounds().Width() - 70, 155,
+               Bounds().Width() - 10, 175 );
+    fOpenButton = new BButton( r, NULL, "Open", new BMessage( SCAN_OPEN ) );
+    fOpenButton->MakeDefault( true );
+    AddChild( fOpenButton );
+
+    DetectVolumes();
+}
+
+void ScanView::MessageReceived( BMessage * message )
+{
+    switch( message->what )
+    {
+        case SCAN_RADIO:
+        {
+            if( fRadioDetected->Value() )
+            {
+                fField->SetEnabled( true );
+                fFolderControl->SetEnabled( false );
+                fBrowseButton->SetEnabled( false );
+                fOpenButton->SetEnabled( fPopUp->CountItems() > 0 );
+            }
+            else
+            {
+                fField->SetEnabled( false );
+                fFolderControl->SetEnabled( true );
+                fBrowseButton->SetEnabled( true );
+                fOpenButton->SetEnabled( true );
+            }
+            break;
+        }
+
+        case SCAN_BROWSE_BUTTON:
+        {
+            fFilePanel->Show();
+            break;
+        }
+
+        case B_REFS_RECEIVED:
+        {
+            entry_ref ref;
+            if( message->FindRef( "refs", 0, &ref ) == B_OK )
+            {
+                BPath * path = new BPath( &ref );
+                fFolderControl->SetText( path->Path() );
+            }
+            break;
+        }
+        
+        case SCAN_OPEN:
+        {
+            if( fRadioDetected->Value() )
+            {
+                fManager->ScanVolumes( (char*)
+                                       fPopUp->FindMarked()->Label() );
+            }
+            else
+            {
+                fManager->ScanVolumes( (char*) fFolderControl->Text() );
+            }
+            break;
+        }
+        
+        default:
+            BView::MessageReceived( message );
+    }
+}
+
+void ScanView::UpdateIntf( HBStatus status )
+{
+    switch( status.fMode )
+    {
+        case HB_MODE_SCANNING:
+        {
+            fRadioDetected->SetEnabled( false );
+            fRadioFolder->SetEnabled( false );
+            fField->SetEnabled( false );
+            fFolderControl->SetEnabled( false );
+            fBrowseButton->SetEnabled( false );
+            fOpenButton->SetEnabled( false );
+
+            char string[1024]; memset( string, 0, 1024 );
+            if( !status.fScannedTitle )
+            {
+                sprintf( string, "Opening %s...",
+                         status.fScannedVolume );
+            }
+            else
+            {
+                sprintf( string, "Scanning %s, title %d...",
+                         status.fScannedVolume, status.fScannedTitle );
+            }
+            fStatusString->SetText( string );
+            break;
+        }
+
+        case HB_MODE_INVALID_VOLUME:
+        {
+            fRadioDetected->SetEnabled( true );
+            fRadioFolder->SetEnabled( true );
+
+            if( fRadioDetected->Value() )
+            {
+                fField->SetEnabled( true );
+                fFolderControl->SetEnabled( false );
+                fBrowseButton->SetEnabled( false );
+                fOpenButton->SetEnabled( fPopUp->CountItems() > 0 );
+            }
+            else
+            {
+                fField->SetEnabled( false );
+                fFolderControl->SetEnabled( true );
+                fBrowseButton->SetEnabled( true );
+                fOpenButton->SetEnabled( true );
+            }
+            
+            fStatusString->SetText( "Invalid volume." );
+            break;
+        }
+
+        default:
+            break;
+    }
+}
+
+void ScanView::DetectVolumes()
+{
+    BVolumeRoster   * roster  = new BVolumeRoster();
+    BVolume         * volume = new BVolume();
+    fs_info           info;
+    int               device;
+    device_geometry   geometry;
+
+    /* Parse mounted volumes */
+    while( roster->GetNextVolume( volume ) == B_NO_ERROR )
+    {
+        /* open() and ioctl() for more informations */
+        fs_stat_dev( volume->Device(), &info );
+        if( ( device = open( info.device_name, O_RDONLY ) ) < 0 )
+        {
+            continue;
+        }
+
+        if( ioctl( device, B_GET_GEOMETRY, &geometry,
+                   sizeof( geometry ) ) < 0 )
+
+        {
+            continue;
+        }
+
+        /* Get the volume name */
+        char volumeName[B_FILE_NAME_LENGTH];
+        volume->GetName( volumeName );
+
+        if( volume->IsReadOnly() && geometry.device_type == B_CD )
+        {
+            /* May be a DVD */
+            fPopUp->AddItem( new BMenuItem( info.device_name, NULL ) );
+        }
+        else if( geometry.device_type == B_DISK )
+        {
+            /* May be a hard drive. Look for VIDEO_TS folders on it */
+            BQuery * query = new BQuery();
+
+            if( query->SetVolume( volume ) != B_OK )
+            {
+                delete query;
+                continue;
+            }
+
+            if( query->SetPredicate( "name = VIDEO_TS.BUP" ) != B_OK )
+            {
+                delete query;
+                continue;
+            }
+
+            query->Fetch();
+
+            BEntry entry, parentEntry;
+            BPath  path;
+            while( query->GetNextEntry( &entry ) == B_OK )
+            {
+                entry.GetParent( &parentEntry );
+                parentEntry.GetPath( &path );
+
+                fPopUp->AddItem( new BMenuItem( path.Path(), NULL ) );
+            }
+
+            delete query;
+        }
+    }
+
+    if( fPopUp->CountItems() > 0 )
+    {
+        fPopUp->ItemAt( 0 )->SetMarked( true );
+        fRadioDetected->SetValue( true );
+        fFolderControl->SetEnabled( false );
+        fBrowseButton->SetEnabled( false );
+    }
+    else
+    {
+        fRadioFolder->SetValue( true );
+        fField->SetEnabled( false );
+    }
+}
+
diff --git a/beos/ScanView.h b/beos/ScanView.h
new file mode 100644 (file)
index 0000000..5e2514b
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: ScanView.h,v 1.2 2003/10/13 22:23:02 titer Exp $
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://beos.titer.org/handbrake/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_SCAN_VIEW_H
+#define HB_SCAN_VIEW_H
+
+#include <View.h>
+class BButton;
+class BFilePanel;
+class BMenuField;
+class BPopUpMenu;
+class BRadioButton;
+class BStringView;
+class BTextControl;
+
+#include "Common.h"
+
+#define SCAN_RADIO         'scra'
+#define SCAN_BROWSE_BUTTON 'sbrb'
+#define SCAN_OPEN          'scop'
+
+class ScanView : public BView
+{
+    public:
+                       ScanView( HBManager * manager );
+        void           MessageReceived( BMessage * message );
+        void           UpdateIntf( HBStatus status );
+
+    private:
+        void           DetectVolumes();
+
+        HBManager    * fManager;
+        
+        BRadioButton * fRadioDetected;
+        BRadioButton * fRadioFolder;
+        BMenuField   * fField;
+        BPopUpMenu   * fPopUp;
+        BTextControl * fFolderControl;
+        BButton      * fBrowseButton;
+        BFilePanel   * fFilePanel;
+        BStringView  * fStatusString;
+        BButton      * fOpenButton;
+};
+
+#endif
index 12eed05..95030d8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Ac3Decoder.cpp,v 1.12 2003/09/30 14:38:15 titer Exp $
+/* $Id: Ac3Decoder.cpp,v 1.20 2003/10/13 10:58:24 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -13,101 +13,160 @@ extern "C" {
 }
 
 HBAc3Decoder::HBAc3Decoder( HBManager * manager, HBAudio * audio )
-    : HBThread( "ac3decoder" )
 {
-    fManager     = manager;
-    fAudio       = audio;
+    fManager = manager;
+    fAudio   = audio;
 
+    fLock = new HBLock();
+    fUsed = false;
+
+    /* Init liba52 */
+    fState    = a52_init( 0 );
+    fInFlags  = 0;
+    fOutFlags = A52_STEREO;
+
+    /* Lame wants samples from -32768 to 32768 */
+    fSampleLevel = 32768.0;
+    
     /* Max size for a A52 frame is 3840 bytes */
-    fAc3Frame    = new HBBuffer( 3840 );
-    fAc3Buffer   = NULL;
-    fPosInBuffer = 0;
-    fPosition    = 0;
+    fAc3Frame        = new HBBuffer( 3840 );
+    fAc3Frame->fSize = 0;
+    fAc3Buffer       = NULL;
+    fPosInBuffer     = 0;
+    fRawBuffer       = NULL;
 }
 
 HBAc3Decoder::~HBAc3Decoder()
 {
+    if( fRawBuffer ) delete fRawBuffer;
+    if( fAc3Buffer ) delete fAc3Buffer;
     delete fAc3Frame;
+    a52_free( fState );
+    delete fLock;
 }
 
-void HBAc3Decoder::DoWork()
+bool HBAc3Decoder::Work()
 {
-    /* Init liba52 */
-    a52_state_t * state       = a52_init( 0 );
-    int           inFlags     = 0;
-    int           outFlags    = A52_STEREO;
-
-    /* Lame wants samples from -32768 to 32768 */
-    float         sampleLevel = 32768;
-
-    int           frameSize;
-    HBBuffer    * rawBuffer;
-    sample_t    * samples;
-
-    /* Main loop */
+    if( !Lock() )
+    {
+        return false;
+    }
+   
+    bool didSomething = false;
+    
+    sample_t * samples;
     for( ;; )
     {
-        while( fSuspend )
+        /* Try to push the latest decoded buffer */
+        if( fRawBuffer )
         {
-            Snooze( 10000 );
+            if( fAudio->fRawFifo->Push( fRawBuffer ) )
+            {
+                fRawBuffer = NULL;
+            }
+            else
+            {
+                break;
+            }
         }
 
-        fAc3Frame->fSize = 0;
-
-        /* Get a frame header (7 bytes) */
-        if( !( GetBytes( 7 ) ) )
+        /* Get a new frame */
+        if( fAc3Frame->fSize < 7 )
         {
-            break;
-        }
-
-        /* Get the size of the current frame */
-        frameSize = a52_syncinfo( fAc3Frame->fData, &inFlags,
-                                  &fAudio->fInSampleRate,
-                                  &fAudio->fInBitrate );
+            /* Get a frame header (7 bytes) */
+            if( !( GetBytes( 7 ) ) )
+            {
+                break;
+            }
 
-        if( !frameSize )
-        {
-            Log( "HBAc3Decoder : a52_syncinfo failed" );
-            fManager->Error();
-            break;
+            /* Get the size of the current frame */
+            fFrameSize = a52_syncinfo( fAc3Frame->fData, &fInFlags,
+                                       &fAudio->fInSampleRate,
+                                       &fAudio->fInBitrate );
+            if( !fFrameSize )
+            {
+                Log( "HBAc3Decoder : a52_syncinfo failed" );
+                fManager->Error( HB_ERROR_A52_SYNC );
+                return false;
+            }
         }
 
-        /* Get the whole frame */
-        if( !( GetBytes( (uint32_t) frameSize ) ) )
+        /* In case the audio should start later than the video,
+           insert some silence */
+        if( fAudio->fDelay > 3 * 256 * 1000 / fAudio->fInSampleRate  )
         {
-            break;
+            fRawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) );
+            for( uint32_t i = 0; i < 12 * 256; i++ )
+            {
+                ((float*)fRawBuffer->fData)[i] = 0;
+            }
+            fAudio->fDelay -= 6 * 256 * 1000 / fAudio->fInSampleRate;
+            continue;
         }
+        if( fAc3Frame->fSize >= 7 )
+        {
+            /* Get the whole frame */
+            if( !( GetBytes( (uint32_t) fFrameSize ) ) )
+            {
+                break;
+            }
 
-        /* Feed liba52 */
-        a52_frame( state, fAc3Frame->fData, &outFlags, &sampleLevel, 0 );
+            /* Feed liba52 */
+            a52_frame( fState, fAc3Frame->fData, &fOutFlags,
+                       &fSampleLevel, 0 );
 
-        /* 6 blocks per frame, 256 samples per block */
-        rawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) );
-        rawBuffer->fPosition = fPosition;
-        for( int i = 0; i < 6; i++ )
-        {
-            /* Decode a block */
-            a52_block( state );
+            /* 6 blocks per frame, 256 samples per block */
+            fRawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) );
+            fRawBuffer->fPosition = fPosition;
+            for( int i = 0; i < 6; i++ )
+            {
+                /* Decode a block */
+                a52_block( fState );
 
-            /* Get a pointer to the raw data */
-            samples = a52_samples( state );
+                /* Get a pointer to the raw data */
+                samples = a52_samples( fState );
 
-            /* Copy left channel data */
-            memcpy( (float*) rawBuffer->fData + i * 256,
-                    samples,
-                    256 * sizeof( float ) );
+                /* Copy left channel data */
+                memcpy( (float*) fRawBuffer->fData + i * 256,
+                        samples,
+                        256 * sizeof( float ) );
 
-            /* Copy right channel data */
-            memcpy( (float*) rawBuffer->fData + ( 6 + i ) * 256,
-                    samples + 256,
-                    256 * sizeof( float ) );
-        }
+                /* Copy right channel data */
+                memcpy( (float*) fRawBuffer->fData + ( 6 + i ) * 256,
+                        samples + 256,
+                        256 * sizeof( float ) );
+            }
 
-        if( !Push( fAudio->fRawFifo, rawBuffer ) )
-        {
-            break;
+            fAc3Frame->fSize = 0;
+
+            didSomething = true;
         }
     }
+
+    Unlock();
+
+    return didSomething;
+}
+
+bool HBAc3Decoder::Lock()
+{
+    fLock->Lock();
+    if( fUsed )
+    {
+        fLock->Unlock();
+        return false;
+    }
+    fUsed = true;
+    fLock->Unlock();
+    return true;
+}
+
+void HBAc3Decoder::Unlock()
+{
+    fLock->Lock();
+    fUsed = false;
+    fLock->Unlock();
 }
 
 /* GetBytes() : pops buffers from the AC3 fifo until fAc3Frame
@@ -118,7 +177,7 @@ bool HBAc3Decoder::GetBytes( uint32_t size )
     {
         if( !fAc3Buffer )
         {
-            if( !( fAc3Buffer = Pop( fAudio->fAc3Fifo ) ) )
+            if( !( fAc3Buffer = fAudio->fAc3Fifo->Pop() ) )
             {
                 return false;
             }
index 8226bb3..41ac483 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Ac3Decoder.h,v 1.6 2003/09/30 14:38:15 titer Exp $
+/* $Id: Ac3Decoder.h,v 1.10 2003/10/07 20:58:12 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -8,26 +8,40 @@
 #define HB_AC3_DECODER_H
 
 #include "Common.h"
-#include "Thread.h"
 
-class HBAc3Decoder : public HBThread
+class HBAc3Decoder
 {
     public:
-                    HBAc3Decoder( HBManager * manager,
-                                  HBAudio * audio );
-                    ~HBAc3Decoder();
+                      HBAc3Decoder( HBManager * manager,
+                                    HBAudio * audio );
+                      ~HBAc3Decoder();
+        bool          Work();
 
     private:
-        void        DoWork();
-        bool        GetBytes( uint32_t size );
-
-        HBManager * fManager;
-        HBAudio   * fAudio;
-
-        HBBuffer  * fAc3Frame;
-        HBBuffer  * fAc3Buffer;
-        uint32_t    fPosInBuffer;
-        float       fPosition;
+        bool          Lock();
+        void          Unlock();
+        bool          GetBytes( uint32_t size );
+
+        HBManager   * fManager;
+        HBAudio     * fAudio;
+        
+        HBLock      * fLock;
+        bool          fUsed;
+
+        /* liba52 */
+        a52_state_t * fState;
+        int           fInFlags;
+        int           fOutFlags;
+        float         fSampleLevel;
+
+        /* buffers */
+        HBBuffer    * fAc3Frame;
+        HBBuffer    * fAc3Buffer;
+        uint32_t      fPosInBuffer;
+        HBBuffer    * fRawBuffer;
+
+        float         fPosition;
+        int           fFrameSize;
 };
 
 #endif
index 3b77b9c..4a84fe8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: AviMuxer.cpp,v 1.14 2003/09/30 14:38:15 titer Exp $
+/* $Id: AviMuxer.cpp,v 1.17 2003/10/09 23:33:36 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -149,7 +149,7 @@ void HBAviIndex::WriteInt32( uint32_t val )
 HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title,
                         HBAudio * audio1, HBAudio * audio2,
                         char * fileName )
-    : HBThread( "avimuxer" )
+    : HBThread( "avimuxer", HB_NORMAL_PRIORITY )
 {
     fManager        = manager;
     fTitle          = title;
@@ -163,6 +163,8 @@ HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title,
 
     fRiffBytesCount = 2040;
     fMoviBytesCount = 4;
+
+    Run();
 }
 
 void HBAviMuxer::DoWork()
@@ -171,7 +173,7 @@ void HBAviMuxer::DoWork()
     if( !( fFile = fopen( fFileName, "w" ) ) )
     {
         Log( "HBAviMuxer: fopen failed" );
-        fManager->Error();
+        fManager->Error( HB_ERROR_AVI_WRITE );
         return;
     }
 
index b9bb3e0..4087a00 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Common.cpp,v 1.29 2003/09/30 21:21:32 titer Exp $
+/* $Id: Common.cpp,v 1.31 2003/10/07 22:48:31 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -92,6 +92,74 @@ uint64_t GetDate()
     return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec );
 }
 
+int GetCPUCount()
+{
+    int CPUCount = 1;
+
+#if defined( SYS_BEOS )
+    system_info info;
+    get_system_info( &info );
+    CPUCount = info.cpu_count;
+
+#elif defined( SYS_MACOSX )
+    FILE * info;
+    char   buffer[256];
+
+    if( ( info = popen( "/usr/sbin/sysctl hw.ncpu", "r" ) ) )
+    {
+        if( fgets( buffer, 256, info ) )
+        {
+            int count;
+            if( sscanf( buffer, "hw.ncpu: %d", &count ) == 1 )
+            {
+                CPUCount = count;
+            }
+            else
+            {
+                Log( "GetCPUCount: sscanf() failed" );
+            }
+        }
+        else
+        {
+            Log( "GetCPUCount: fgets() failed" );
+        }
+        fclose( info );
+    }
+    else
+    {
+        Log( "GetCPUCount: popen() failed" );
+    }
+   
+#elif defined( SYS_LINUX )
+    FILE * info;
+    char   buffer[256];
+
+    if( ( info = fopen( "/proc/cpuinfo", "r" ) ) )
+    {
+        int count = 0;
+        while( fgets( buffer, 256, info ) )
+        {
+            if( !memcmp( buffer, "processor",
+                         sizeof( "processor" ) - 1 ) )
+            {
+                count++;
+            }
+        }
+        CPUCount = count;
+        fclose( info );
+    }
+    else
+    {
+        Log( "GetCPUCount: fopen() failed" );
+    }
+    
+#endif
+    CPUCount = MAX( 1, CPUCount );
+    CPUCount = MIN( CPUCount, 8 );
+
+    return CPUCount;
+}
+
 #define HBLIST_DEFAULT_SIZE 20
 
 HBList::HBList()
index f4d40c8..3c138e2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Common.h,v 1.28 2003/10/03 16:18:08 titer Exp $
+/* $Id: Common.h,v 1.34 2003/10/13 17:49:58 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -16,6 +16,8 @@
 typedef uint8_t byte_t;
 
 /* Misc structures */
+typedef struct a52_state_s a52_state_t;
+typedef struct lame_global_struct lame_global_flags;
 typedef struct dvdplay_s * dvdplay_ptr;
 typedef struct mpeg2dec_s mpeg2dec_t;
 typedef struct AVPicture AVPicture;
@@ -43,6 +45,7 @@ class HBScanner;
 class HBStatus;
 class HBThread;
 class HBTitle;
+class HBWorker;
 
 /* Handy macros */
 #ifndef MIN
@@ -61,22 +64,36 @@ void     Snooze( uint64_t time );
 void     Log( char * log, ... );
 char   * LanguageForCode( int code );
 uint64_t GetDate();
+int      GetCPUCount();
 
 /* Possible states */
 typedef enum
 {
-    HB_MODE_UNDEF          = 0000,
-    HB_MODE_NEED_VOLUME    = 0001,
-    HB_MODE_SCANNING       = 0002,
-    HB_MODE_INVALID_VOLUME = 0004,
-    HB_MODE_READY_TO_RIP   = 0010,
-    HB_MODE_ENCODING       = 0020,
-    HB_MODE_SUSPENDED      = 0040,
-    HB_MODE_DONE           = 0100,
-    HB_MODE_CANCELED       = 0200,
-    HB_MODE_ERROR          = 0400
+    HB_MODE_UNDEF          = 00000,
+    HB_MODE_NEED_VOLUME    = 00001,
+    HB_MODE_SCANNING       = 00002,
+    HB_MODE_INVALID_VOLUME = 00004,
+    HB_MODE_READY_TO_RIP   = 00010,
+    HB_MODE_ENCODING       = 00020,
+    HB_MODE_SUSPENDED      = 00040,
+    HB_MODE_STOPPING       = 00100,
+    HB_MODE_DONE           = 00200,
+    HB_MODE_CANCELED       = 00400,
+    HB_MODE_ERROR          = 01000
 } HBMode;
 
+/* Possible errors */
+typedef enum
+{
+    HB_ERROR_A52_SYNC = 0,
+    HB_ERROR_AVI_WRITE,
+    HB_ERROR_DVD_OPEN,
+    HB_ERROR_DVD_READ,
+    HB_ERROR_MP3_INIT,
+    HB_ERROR_MP3_ENCODE,
+    HB_ERROR_MPEG4_INIT
+} HBError;
+
 class HBStatus
 {
     public:
@@ -96,6 +113,9 @@ class HBStatus
         uint64_t fStartDate;
         uint32_t fRemainingTime; /* in seconds */
         uint64_t fSuspendDate;
+
+        /* HB_MODE_ERROR */
+        HBError  fError;
 };
 
 class HBList
@@ -130,6 +150,8 @@ class HBAudio
         int            fInBitrate;
         int            fOutBitrate;
 
+        int64_t        fDelay; /* in ms */
+
         /* Fifos */
         HBFifo       * fAc3Fifo;
         HBFifo       * fRawFifo;
@@ -187,6 +209,7 @@ class HBTitle
         HBResizer      * fResizer;
         HBMpeg4Encoder * fMpeg4Encoder;
         HBAviMuxer     * fAviMuxer;
+        HBWorker       * fWorkers[4];
 };
 
 #endif
index 27c20d0..8f7835f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: DVDReader.cpp,v 1.12 2003/10/03 16:49:19 titer Exp $
+/* $Id: DVDReader.cpp,v 1.17 2003/10/09 23:33:36 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
 #include <dvdplay/nav.h>
 
 HBDVDReader::HBDVDReader( HBManager * manager, HBTitle * title )
-    : HBThread( "dvdreader" )
+    : HBThread( "dvdreader", HB_NORMAL_PRIORITY )
 {
     fManager = manager;
     fTitle   = title;
+
+    Run();
 }
 
 void HBDVDReader::DoWork()
@@ -29,7 +31,7 @@ void HBDVDReader::DoWork()
     if( !vmg )
     {
         Log( "HBDVDReader: dvdplay_open() failed" );
-        fManager->Error();
+        fManager->Error( HB_ERROR_DVD_OPEN );
         return;
     }
 
@@ -69,7 +71,7 @@ void HBDVDReader::DoWork()
             {
                 Log( "HBDVDReader: could not dvdplay_read()" );
                 delete dvdBuffer;
-                fManager->Error();
+                fManager->Error( HB_ERROR_DVD_READ );
                 break;
             }
 
index 35bcb04..d1d051c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Fifo.cpp,v 1.14 2003/10/02 15:44:52 titer Exp $
+/* $Id: Fifo.cpp,v 1.15 2003/10/13 14:12:18 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -51,7 +51,8 @@ HBFifo::HBFifo( int capacity )
 
 HBFifo::~HBFifo()
 {
-    Log( "HBFifo::~HBFifo : trashing %d buffers", Size() );
+    Log( "HBFifo::~HBFifo: trashing %d buffer%s",
+         Size(), Size() ? "s" : "" );
     
     /* Empty the fifo */
     while( fWhereToPush != fWhereToPop )
index 583bda3..826ceea 100644 (file)
-/* $Id: Manager.cpp,v 1.47 2003/10/05 14:28:40 titer Exp $
+/* $Id: Manager.cpp,v 1.68 2003/10/13 23:42:03 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
    It may be used under the terms of the GNU General Public License. */
 
-#include "Manager.h"
-#include "Fifo.h"
-#include "Scanner.h"
+#include "Ac3Decoder.h"
+#include "AviMuxer.h"
 #include "DVDReader.h"
-#include "MpegDemux.h"
+#include "Fifo.h"
+#include "Manager.h"
+#include "Mp3Encoder.h"
 #include "Mpeg2Decoder.h"
 #include "Mpeg4Encoder.h"
-#include "Ac3Decoder.h"
-#include "Mp3Encoder.h"
-#include "AviMuxer.h"
+#include "MpegDemux.h"
 #include "Resizer.h"
+#include "Scanner.h"
+#include "Worker.h"
 
 #include <ffmpeg/avcodec.h>
 
 /* Public methods */
 
-HBManager::HBManager( bool debug )
-    : HBThread( "manager" )
+HBManager::HBManager( bool debug, int cpuCount )
+    : HBThread( "manager", HB_NORMAL_PRIORITY )
 {
-    fPid         = 0;
-
-    fStopScan    = false;
-    fStopRip     = false;
-    fRipDone     = false;
-    fError       = false;
-
-    fScanner     = NULL;
-
-    fStatus.fMode = HB_MODE_NEED_VOLUME;
-    fNeedUpdate   = true;
-
     /* See Log() in Common.cpp */
     if( debug )
     {
-        setenv( "HB_DEBUG", "1", 1 );
+        putenv( "HB_DEBUG=1" );
+    }
+
+    /* Check CPU count */
+    if( !cpuCount )
+    {
+        fCPUCount = GetCPUCount();
+        Log( "HBManager::HBManager: %d CPU%s detected", fCPUCount,
+             ( fCPUCount > 1 ) ? "s" : "" );
     }
     else
     {
-        unsetenv( "HB_DEBUG" );
+        fCPUCount = cpuCount;
+        if( fCPUCount < 1 )
+        {
+            Log( "HBManager::HBManager: invalid CPU count (%d), "
+                 "using 1", fCPUCount );
+            fCPUCount = 1;
+        }
+        else if( fCPUCount > 8 )
+        {
+            Log( "HBManager::HBManager: invalid CPU count (%d), "
+                 "using 8", fCPUCount );
+            fCPUCount = 8;
+        }
+        Log( "HBManager::HBManager: user specified %d CPU%s",
+             fCPUCount, ( fCPUCount > 1 ) ? "s" : "" );
     }
 
-    fCurTitle    = NULL;
-    fCurAudio1   = NULL;
-    fCurAudio2   = NULL;
-
     /* Init ffmpeg's libavcodec */
     avcodec_init();
 //    register_avcodec( &mpeg4_encoder );
     avcodec_register_all();
 
+    /* Initialization */
+    fStopScan = false;
+    fStopRip  = false;
+    fRipDone  = false;
+    fError    = false;
+
+    fScanner = NULL;
+
+    fStatusLock   = new HBLock();
+    fStatus.fMode = HB_MODE_NEED_VOLUME;
+    fNeedUpdate   = true;
+
+    fCurTitle  = NULL;
+    fCurAudio1 = NULL;
+    fCurAudio2 = NULL;
+
     Run();
 }
 
 HBManager::~HBManager()
 {
     /* Stop ripping if needed */
-    StopRip();
-    while( fStopRip )
+    fStatusLock->Lock();
+    if( fStatus.fMode == HB_MODE_ENCODING )
     {
-        Snooze( 10000 );
-    }
+        fStatusLock->Unlock();
 
-    Stop();
+        StopRip();
+        while( fStopRip )
+        {
+            Snooze( 10000 );
+        }
+    }
+    else
+    {
+        fStatusLock->Unlock();
+    }
 
     /* Stop scanning if needed */
     if( fScanner )
@@ -76,24 +107,24 @@ HBManager::~HBManager()
 
     /* Remove temp files */
     char command[1024]; memset( command, 0, 1024 );
-    sprintf( command, "rm -f /tmp/HB.%d.*", fPid );
+    sprintf( command, "rm -f /tmp/HB.%d.*", GetPid() );
     system( command );
+
+    delete fStatusLock;
 }
 
 void HBManager::DoWork()
 {
-    fPid = (int) getpid();
-
     while( !fDie )
     {
-        /* Terminate dying threads */
         if( fStopScan )
         {
-            fStopScan = false;
-
+            /* Destroy the thread */
             delete fScanner;
             fScanner = NULL;
 
+            /* Update interface */
+            fStatusLock->Lock();
             if( fStatus.fTitleList && fStatus.fTitleList->CountItems() )
             {
                 fStatus.fMode = HB_MODE_READY_TO_RIP;
@@ -103,83 +134,47 @@ void HBManager::DoWork()
                 fStatus.fMode = HB_MODE_INVALID_VOLUME;
             }
             fNeedUpdate = true;
+            fStatusLock->Unlock();
+
+            fStopScan = false;
         }
 
-        if( fStopRip || fError )
+        if( fStopRip || fError || fRipDone )
         {
-            delete fCurTitle->fDVDReader;
-            delete fCurTitle->fMpegDemux;
-            delete fCurTitle->fMpeg2Decoder;
-            delete fCurTitle->fResizer;
-            delete fCurTitle->fMpeg4Encoder;
-            delete fCurTitle->fAviMuxer;
-
-            if( fCurAudio1 )
+            if( fRipDone )
             {
-                delete fCurAudio1->fAc3Decoder;
-                delete fCurAudio1->fMp3Encoder;
+                /* Wait a bit to avoid trashing frames in fifos -
+                   That's kinda ugly */
+                while( fCurTitle->fPSFifo->Size() ||
+                       ( fCurTitle->fMpeg2Fifo->Size() &&
+                         ( !fCurAudio1 || fCurAudio1->fAc3Fifo->Size() ) &&
+                         ( !fCurAudio2 || fCurAudio2->fAc3Fifo->Size() ) ) )
+                {
+                    Snooze( 10000 );
+                }
+                Snooze( 500000 );
             }
-
-            if( fCurAudio2 )
-            {
-                delete fCurAudio2->fAc3Decoder;
-                delete fCurAudio2->fMp3Encoder;
-            }
-
-            delete fCurTitle->fPSFifo;
-            delete fCurTitle->fMpeg2Fifo;
-            delete fCurTitle->fRawFifo;
-            delete fCurTitle->fResizedFifo;
-            delete fCurTitle->fMpeg4Fifo;
-
-            if( fCurAudio1 )
-            {
-                delete fCurAudio1->fAc3Fifo;
-                delete fCurAudio1->fRawFifo;
-                delete fCurAudio1->fMp3Fifo;
-            }
-
-            if( fCurAudio2 )
-            {
-                delete fCurAudio2->fAc3Fifo;
-                delete fCurAudio2->fRawFifo;
-                delete fCurAudio2->fMp3Fifo;
-            }
-
-            fStatus.fMode = fError ? HB_MODE_ERROR : HB_MODE_CANCELED;
-            fStopRip = false;
-            fError = false;
-            fNeedUpdate = true;
-        }
-
-        if( fRipDone )
-        {
-            /* This is UGLY ! */
-            while( fCurTitle->fPSFifo->Size() ||
-                   fCurTitle->fMpeg2Fifo->Size() ||
-                   fCurTitle->fRawFifo->Size() ||
-                   fCurTitle->fResizedFifo->Size() ||
-                   ( fCurAudio1 && fCurAudio1->fAc3Fifo->Size() ) ||
-                   ( fCurAudio1 && fCurAudio1->fRawFifo->Size() ) ||
-                   ( fCurAudio2 && fCurAudio2->fAc3Fifo->Size() ) ||
-                   ( fCurAudio2 && fCurAudio2->fRawFifo->Size() ) )
+            else
             {
-                Snooze( 10000 );
+                fStatusLock->Lock();
+                fStatus.fMode = HB_MODE_STOPPING;
+                fNeedUpdate = true;
+                fStatusLock->Unlock();
             }
-
-            while( fCurTitle->fMpeg4Fifo->Size() &&
-                   ( !fCurAudio1 || fCurAudio1->fMp3Fifo->Size() ) &&
-                   ( !fCurAudio2 || fCurAudio2->fMp3Fifo->Size() ) )
+            
+            /* Stop threads */
+            delete fCurTitle->fDVDReader;
+            delete fCurTitle->fAviMuxer;
+            for( int i = 0; i < fCPUCount; i++ )
             {
-                Snooze( 10000 );
+                delete fCurTitle->fWorkers[i];
             }
 
-            delete fCurTitle->fDVDReader;
+            /* Clean up */
             delete fCurTitle->fMpegDemux;
             delete fCurTitle->fMpeg2Decoder;
             delete fCurTitle->fResizer;
             delete fCurTitle->fMpeg4Encoder;
-            delete fCurTitle->fAviMuxer;
 
             if( fCurAudio1 )
             {
@@ -193,6 +188,7 @@ void HBManager::DoWork()
                 delete fCurAudio2->fMp3Encoder;
             }
 
+            /* Destroy fifos */
             delete fCurTitle->fPSFifo;
             delete fCurTitle->fMpeg2Fifo;
             delete fCurTitle->fRawFifo;
@@ -213,9 +209,16 @@ void HBManager::DoWork()
                 delete fCurAudio2->fMp3Fifo;
             }
 
-            fStatus.fMode = HB_MODE_DONE;
-            fRipDone = false;
+            /* Update interface */
+            fStatusLock->Lock();
+            fStatus.fMode = fStopRip ? HB_MODE_CANCELED :
+                ( fError ? HB_MODE_ERROR : HB_MODE_DONE );
             fNeedUpdate = true;
+            fStatusLock->Unlock();
+
+            fStopRip = false;
+            fError   = false;
+            fRipDone = false;
         }
 
         Snooze( 10000 );
@@ -224,23 +227,25 @@ void HBManager::DoWork()
 
 bool HBManager::NeedUpdate()
 {
+    fStatusLock->Lock();
     if( fNeedUpdate )
     {
         fNeedUpdate = false;
+        fStatusLock->Unlock();
         return true;
     }
-
+    fStatusLock->Unlock();
+    
     return false;
 }
 
 HBStatus HBManager::GetStatus()
 {
-    return fStatus;
-}
-
-int HBManager::GetPid()
-{
-    return fPid;
+    fStatusLock->Lock();
+    HBStatus status = fStatus;
+    fStatusLock->Unlock();
+    
+    return status;
 }
 
 void HBManager::ScanVolumes( char * device )
@@ -254,12 +259,13 @@ void HBManager::ScanVolumes( char * device )
     }
     
     fScanner = new HBScanner( this, device );
-    fScanner->Run();
 
+    fStatusLock->Lock();
     fStatus.fMode          = HB_MODE_SCANNING;
     fStatus.fScannedVolume = strdup( device );
     fStatus.fScannedTitle  = 0;
     fNeedUpdate            = true;
+    fStatusLock->Unlock();
 }
 
 void HBManager::StartRip( HBTitle * title, HBAudio * audio1,
@@ -282,86 +288,77 @@ void HBManager::StartRip( HBTitle * title, HBAudio * audio1,
 
     FixPictureSettings( title );
 
-    Log( "HBManager::StartRip : device: %s, title: %d",
-         title->fDevice, title->fIndex );
-    Log( "    - video : %dx%d -> %dx%d, bitrate = %d, 2-pass = %s",
+    Log( "HBManager::StartRip:" );
+    Log( "- device: %s, title: %d", title->fDevice, title->fIndex );
+    Log( "- video: %dx%d->%dx%d, bitrate=%d, 2-pass=%s, deinterlace=%s",
          title->fInWidth, title->fInHeight,
          title->fOutWidth, title->fOutHeight,
-         title->fBitrate, title->fTwoPass ? "yes" : "no" );
-    Log( "    - cropping: top=%d, bottom=%d, left=%d, right=%d",
+         title->fBitrate, title->fTwoPass ? "yes" : "no",
+         title->fDeinterlace ? "yes" : "no" );
+    Log( "- cropping: top=%d, bottom=%d, left=%d, right=%d",
          title->fTopCrop, title->fBottomCrop,
          title->fLeftCrop, title->fRightCrop );
     if( audio1 )
     {
-        Log( "    - audio 1: lang = %s (%x), bitrate = %d",
-             audio1->fDescription, audio1->fId, audio1->fOutBitrate );
+    Log( "- audio 1: lang = %s (%x), bitrate = %d",
+         audio1->fDescription, audio1->fId, audio1->fOutBitrate );
     }
     if( audio2 )
     {
-        Log( "    - audio 2: lang = %s (%x), bitrate = %d",
-             audio2->fDescription, audio1->fId, audio2->fOutBitrate );
+    Log( "- audio 2: lang = %s (%x), bitrate = %d",
+         audio2->fDescription, audio2->fId, audio2->fOutBitrate );
     }
 
-    /* Create fifos & threads */
-
-    title->fPSFifo       = new HBFifo();
-    title->fMpeg2Fifo    = new HBFifo();
-    title->fRawFifo      = new HBFifo();
-    title->fResizedFifo  = new HBFifo();
-    title->fMpeg4Fifo    = new HBFifo();
+    /* Create fifos */
+    title->fPSFifo       = new HBFifo( 256 );
+    title->fMpeg2Fifo    = new HBFifo( 256 );
+    title->fRawFifo      = new HBFifo( 4 );
+    title->fResizedFifo  = new HBFifo( 4 );
+    title->fMpeg4Fifo    = new HBFifo( 4 );
+    if( audio1 )
+    {
+        audio1->fAc3Fifo    = new HBFifo( 256 );
+        audio1->fRawFifo    = new HBFifo( 4 );
+        audio1->fMp3Fifo    = new HBFifo( 4 );
+    }
+    if( audio2 )
+    {
+        audio2->fAc3Fifo    = new HBFifo( 256 );
+        audio2->fRawFifo    = new HBFifo( 4 );
+        audio2->fMp3Fifo    = new HBFifo( 4 );
+    }
 
-    title->fDVDReader    = new HBDVDReader( this, title );
+    /* Create decoders & encoders objects */
     title->fMpegDemux    = new HBMpegDemux( this, title, audio1,
                                             audio2 );
     title->fMpeg2Decoder = new HBMpeg2Decoder( this, title );
     title->fResizer      = new HBResizer( this, title );
     title->fMpeg4Encoder = new HBMpeg4Encoder( this, title );
-    title->fAviMuxer     = new HBAviMuxer( this, title, audio1, audio2,
-                                           file );
-
     if( audio1 )
     {
-        audio1->fAc3Fifo    = new HBFifo();
-        audio1->fRawFifo    = new HBFifo();
-        audio1->fMp3Fifo    = new HBFifo();
         audio1->fAc3Decoder = new HBAc3Decoder( this, audio1 );
         audio1->fMp3Encoder = new HBMp3Encoder( this, audio1 );
     }
-
     if( audio2 )
     {
-        audio2->fAc3Fifo    = new HBFifo();
-        audio2->fRawFifo    = new HBFifo();
-        audio2->fMp3Fifo    = new HBFifo();
         audio2->fAc3Decoder = new HBAc3Decoder( this, audio2 );
         audio2->fMp3Encoder = new HBMp3Encoder( this, audio2 );
     }
 
-    /* Launch the threads */
-
-    title->fDVDReader->Run();
-    title->fMpegDemux->Run();
-    title->fMpeg2Decoder->Run();
-    title->fResizer->Run();
-    title->fMpeg4Encoder->Run();
-    title->fAviMuxer->Run();
-
-    if( audio1 )
-    {
-        audio1->fAc3Decoder->Run();
-        audio1->fMp3Encoder->Run();
-    }
-
-    if( audio2 )
+    /* Create and launch the threads */
+    title->fDVDReader    = new HBDVDReader( this, title );
+    title->fAviMuxer     = new HBAviMuxer( this, title, audio1, audio2,
+                                           file );
+    for( int i = 0; i < fCPUCount; i++ )
     {
-        audio2->fAc3Decoder->Run();
-        audio2->fMp3Encoder->Run();
+        title->fWorkers[i] = new HBWorker( title, audio1, audio2 );
     }
-
+    
     fCurTitle  = title;
     fCurAudio1 = audio1;
     fCurAudio2 = audio2;
 
+    fStatusLock->Lock();
     fStatus.fMode          = HB_MODE_ENCODING;
     fStatus.fPosition      = 0;
     fStatus.fFrameRate     = 0;
@@ -370,6 +367,7 @@ void HBManager::StartRip( HBTitle * title, HBAudio * audio1,
     fStatus.fRemainingTime = 0;
     fStatus.fSuspendDate   = 0;
     fNeedUpdate = true;
+    fStatusLock->Unlock();
 }
 
 void HBManager::SuspendRip()
@@ -382,27 +380,17 @@ void HBManager::SuspendRip()
     }
 
     fCurTitle->fDVDReader->Suspend();
-    fCurTitle->fMpegDemux->Suspend();
-    fCurTitle->fMpeg2Decoder->Suspend();
-    fCurTitle->fResizer->Suspend();
-    fCurTitle->fMpeg4Encoder->Suspend();
     fCurTitle->fAviMuxer->Suspend();
-
-    if( fCurAudio1 )
+    for( int i = 0; i < fCPUCount; i++ )
     {
-        fCurAudio1->fAc3Decoder->Suspend();
-        fCurAudio1->fMp3Encoder->Suspend();
-    }
-
-    if( fCurAudio2 )
-    {
-        fCurAudio2->fAc3Decoder->Suspend();
-        fCurAudio2->fMp3Encoder->Suspend();
+        fCurTitle->fWorkers[i]->Suspend();
     }
 
+    fStatusLock->Lock();
     fStatus.fMode        = HB_MODE_SUSPENDED;
     fStatus.fSuspendDate = GetDate();
     fNeedUpdate = true;
+    fStatusLock->Unlock();
 }
 
 void HBManager::ResumeRip()
@@ -415,27 +403,17 @@ void HBManager::ResumeRip()
     }
 
     fCurTitle->fDVDReader->Resume();
-    fCurTitle->fMpegDemux->Resume();
-    fCurTitle->fMpeg2Decoder->Resume();
-    fCurTitle->fResizer->Resume();
-    fCurTitle->fMpeg4Encoder->Resume();
     fCurTitle->fAviMuxer->Resume();
-
-    if( fCurAudio1 )
-    {
-        fCurAudio1->fAc3Decoder->Resume();
-        fCurAudio1->fMp3Encoder->Resume();
-    }
-
-    if( fCurAudio2 )
+    for( int i = 0; i < fCPUCount; i++ )
     {
-        fCurAudio2->fAc3Decoder->Resume();
-        fCurAudio2->fMp3Encoder->Resume();
+        fCurTitle->fWorkers[i]->Resume();
     }
 
+    fStatusLock->Lock();
     fStatus.fMode       = HB_MODE_ENCODING;
     fStatus.fStartDate += GetDate() - fStatus.fSuspendDate;
     fNeedUpdate = true;
+    fStatusLock->Unlock();
 }
 
 void HBManager::StopRip()
@@ -448,25 +426,6 @@ void HBManager::StopRip()
     }
 
     /* Stop the threads */
-
-    fCurTitle->fDVDReader->Stop();
-    fCurTitle->fMpegDemux->Stop();
-    fCurTitle->fMpeg2Decoder->Stop();
-    fCurTitle->fMpeg4Encoder->Stop();
-    fCurTitle->fAviMuxer->Stop();
-
-    if( fCurAudio1 )
-    {
-        fCurAudio1->fAc3Decoder->Stop();
-        fCurAudio1->fMp3Encoder->Stop();
-    }
-
-    if( fCurAudio2 )
-    {
-        fCurAudio2->fAc3Decoder->Stop();
-        fCurAudio2->fMp3Encoder->Stop();
-    }
-
     fStopRip = true;
 }
 
@@ -545,7 +504,7 @@ uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image )
 
     /* Get the original image from the temp file */
     char fileName[1024]; memset( fileName, 0, 1024 );
-    sprintf( fileName, "/tmp/HB.%d.%x.%d", fPid, (uint32_t) title,
+    sprintf( fileName, "/tmp/HB.%d.%x.%d", GetPid(), (uint32_t) title,
              image);
     FILE * file = fopen( fileName, "r" );
     fread( buf1, 3 * fInWidth * fInHeight / 2, 1, file );
@@ -632,10 +591,12 @@ uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image )
 
 void HBManager::Scanning( char * volume, int title )
 {
+    fStatusLock->Lock();
     fStatus.fMode       = HB_MODE_SCANNING;
     fStatus.fScannedVolume = volume;
     fStatus.fScannedTitle = title;
     fNeedUpdate = true;
+    fStatusLock->Unlock();
 }
 
 void HBManager::ScanDone( HBList * titleList )
@@ -650,34 +611,14 @@ void HBManager::Done()
     fRipDone = true;
 }
 
-void HBManager::Error()
+void HBManager::Error( HBError error )
 {
     if( fStatus.fMode != HB_MODE_ENCODING )
     {
         return;
     }
 
-    /* Stop the threads */
-
-    fCurTitle->fDVDReader->Stop();
-    fCurTitle->fMpegDemux->Stop();
-    fCurTitle->fMpeg2Decoder->Stop();
-    fCurTitle->fResizer->Stop();
-    fCurTitle->fMpeg4Encoder->Stop();
-    fCurTitle->fAviMuxer->Stop();
-
-    if( fCurAudio1 )
-    {
-        fCurAudio1->fAc3Decoder->Stop();
-        fCurAudio1->fMp3Encoder->Stop();
-    }
-
-    if( fCurAudio2 )
-    {
-        fCurAudio2->fAc3Decoder->Stop();
-        fCurAudio2->fMp3Encoder->Stop();
-    }
-
+    fStatus.fError = error;
     fError = true;
 }
 
@@ -695,6 +636,7 @@ void HBManager::SetPosition( float pos )
         return;
     }
 
+    fStatusLock->Lock();
     fStatus.fPosition = pos;
     fStatus.fFrameRate = (float) fStatus.fFrames /
         ( ( (float) ( GetDate() - fStatus.fStartDate ) ) / 1000000 ) ;
@@ -703,5 +645,6 @@ void HBManager::SetPosition( float pos )
                              ( 1 - fStatus.fPosition ) /
                              ( 1000000 * fStatus.fPosition ) );
     fNeedUpdate = true;
+    fStatusLock->Unlock();
 }
 
index 8aa6cec..dc885e5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Manager.h,v 1.27 2003/09/30 21:21:32 titer Exp $
+/* $Id: Manager.h,v 1.32 2003/10/08 22:20:36 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -13,7 +13,8 @@
 class HBManager : public HBThread
 {
     public:
-                      HBManager( bool debug = false );
+                      HBManager( bool debug = false,
+                                 int cpuCount = 0 );
                       ~HBManager();
         void          DoWork();
 
@@ -29,17 +30,17 @@ class HBManager : public HBThread
         uint8_t     * GetPreview( HBTitle * title, uint32_t image );
 
         /* Methods called by the working threads */
-        int           GetPid();
         void          Scanning( char * volume, int title );
         void          ScanDone( HBList * titleList );
         void          Done();
-        void          Error();
+        void          Error( HBError error );
         void          SetPosition( float pos );
 
     private:
         void          FixPictureSettings( HBTitle * title );
 
         int           fPid;
+        int           fCPUCount;
 
         /* Booleans used in DoWork() */
         bool          fStopScan;
@@ -51,8 +52,10 @@ class HBManager : public HBThread
         HBScanner   * fScanner;
 
         /* Status infos */
+        HBLock      * fStatusLock;
         bool          fNeedUpdate;
         HBStatus      fStatus;
+
         HBTitle     * fCurTitle;
         HBAudio     * fCurAudio1;
         HBAudio     * fCurAudio2;
index b4e9fe8..06d96af 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Mp3Encoder.cpp,v 1.7 2003/09/30 14:38:15 titer Exp $
+/* $Id: Mp3Encoder.cpp,v 1.13 2003/10/08 15:00:20 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
 #include <lame/lame.h>
 
 HBMp3Encoder::HBMp3Encoder( HBManager * manager, HBAudio * audio )
-    : HBThread( "mp3encoder" )
 {
-    fManager      = manager;
-    fAudio        = audio;
+    fManager = manager;
+    fAudio   = audio;
+
+    fLock = new HBLock();
+    fUsed = false;
 
     fRawBuffer    = NULL;
     fPosInBuffer  = 0;
+    fSamplesNb    = 0;
     fLeftSamples  = NULL;
     fRightSamples = NULL;
 
     fPosition     = 0;
+    fInitDone = false;
+    fMp3Buffer = NULL;
 }
 
-void HBMp3Encoder::DoWork()
+bool HBMp3Encoder::Work()
 {
-    /* Wait a first buffer so we are sure that
-       fAudio->fInSampleRate (set the AC3 decoder) is not garbage */
-    while( !fDie && !fAudio->fRawFifo->Size() )
+    if( !Lock() )
     {
-        Snooze( 5000 );
+        return false;
     }
-
-    if( fDie )
+    
+    if( !fInitDone )
     {
-        return;
-    }
+        /* Wait for a first buffer so we know fAudio->fInSampleRate
+           is correct */
+        if( !fAudio->fRawFifo->Size() )
+        {
+            Unlock();
+            return false;
+        }
+        
+        /* The idea is to have exactly one mp3 frame (i.e. 1152 samples) by
+           output buffer. As we are resampling from fInSampleRate to
+           fOutSampleRate, we will give ( 1152 * fInSampleRate ) /
+           ( 2 * fOutSampleRate ) to libmp3lame so we are sure we will
+           never get more than 1 frame at a time */
+        fCount = ( 1152 * fAudio->fInSampleRate ) /
+                    ( 2 * fAudio->fOutSampleRate );
+
+        /* Init libmp3lame */
+        fGlobalFlags = lame_init();
+        lame_set_in_samplerate( fGlobalFlags, fAudio->fInSampleRate );
+        lame_set_out_samplerate( fGlobalFlags, fAudio->fOutSampleRate );
+        lame_set_brate( fGlobalFlags, fAudio->fOutBitrate );
+
+        if( lame_init_params( fGlobalFlags ) == -1 )
+        {
+            Log( "HBMp3Encoder: lame_init_params() failed" );
+            fManager->Error( HB_ERROR_MP3_INIT );
+            return false;
+        }
 
-    /* The idea is to have exactly one mp3 frame (i.e. 1152 samples) by
-       output buffer. As we are resampling from fInSampleRate to
-       fOutSampleRate, we will give ( 1152 * fInSampleRate ) /
-       ( 2 * fOutSampleRate ) to libmp3lame so we are sure we will
-       never get more than 1 frame at a time */
-    uint32_t count = ( 1152 * fAudio->fInSampleRate ) /
-                         ( 2 * fAudio->fOutSampleRate );
-
-    /* Init libmp3lame */
-    lame_global_flags * globalFlags = lame_init();
-    lame_set_in_samplerate( globalFlags, fAudio->fInSampleRate );
-    lame_set_out_samplerate( globalFlags, fAudio->fOutSampleRate );
-    lame_set_brate( globalFlags, fAudio->fOutBitrate );
-
-    if( lame_init_params( globalFlags ) == -1 )
-    {
-        Log( "HBMp3Encoder::DoWork() : lame_init_params() failed" );
-        fManager->Error();
-        return;
-    }
+        fLeftSamples  = (float*) malloc( fCount * sizeof( float ) );
+        fRightSamples = (float*) malloc( fCount * sizeof( float ) );
 
-    fLeftSamples  = (float*) malloc( count * sizeof( float ) );
-    fRightSamples = (float*) malloc( count * sizeof( float ) );
+        fInitDone = true;
+    }
 
-    HBBuffer * mp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER );
+    bool didSomething = false;
 
-    int ret;
     for( ;; )
     {
-        while( fSuspend )
+        if( fMp3Buffer )
         {
-            Snooze( 10000 );
+            if( fAudio->fMp3Fifo->Push( fMp3Buffer ) )
+            {
+                fMp3Buffer = NULL;
+            }
+            else
+            {
+                break;
+            }
         }
-
+        
         /* Get new samples */
-        if( !GetSamples( count ) )
+        if( !GetSamples() )
         {
             break;
         }
 
-        ret = lame_encode_buffer_float( globalFlags,
-                                        fLeftSamples, fRightSamples,
-                                        count, mp3Buffer->fData,
-                                        mp3Buffer->fSize );
+        int ret;
+        fMp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER );
+        ret = lame_encode_buffer_float( fGlobalFlags, fLeftSamples,
+                                        fRightSamples, fCount,
+                                        fMp3Buffer->fData,
+                                        fMp3Buffer->fSize );
 
         if( ret < 0 )
         {
             /* Something wrong happened */
-            Log( "HBMp3Encoder : lame_encode_buffer_float() failed (%d)", ret );
-            fManager->Error();
-            break;
+            Log( "HBMp3Encoder : lame_encode_buffer_float() failed "
+                 "(%d)", ret );
+            fManager->Error( HB_ERROR_MP3_ENCODE );
+            return false;
         }
         else if( ret > 0 )
         {
             /* We got something, send it to the muxer */
-            mp3Buffer->fSize     = ret;
-            mp3Buffer->fKeyFrame = true;
-            mp3Buffer->fPosition = fPosition;
-            Push( fAudio->fMp3Fifo, mp3Buffer );
-            mp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER );
+            fMp3Buffer->fSize     = ret;
+            fMp3Buffer->fKeyFrame = true;
+            fMp3Buffer->fPosition = fPosition;
         }
+        else
+        {
+            delete fMp3Buffer;
+            fMp3Buffer = NULL;
+        }
+        fSamplesNb = 0;
+
+        didSomething = true;
     }
 
-    /* Clean up */
-    delete mp3Buffer;
-    free( fLeftSamples );
-    free( fRightSamples );
+    Unlock();
+    return didSomething;
+}
 
-    lame_close( globalFlags );
+bool HBMp3Encoder::Lock()
+{
+    fLock->Lock();
+    if( fUsed )
+    {
+        fLock->Unlock();
+        return false;
+    }
+    fUsed = true;
+    fLock->Unlock();
+    return true;
 }
 
-bool HBMp3Encoder::GetSamples( uint32_t count )
+void HBMp3Encoder::Unlock()
 {
-    uint32_t samplesNb = 0;
+    fLock->Lock();
+    fUsed = false;
+    fLock->Unlock();
+}
 
-    while( samplesNb < count )
+bool HBMp3Encoder::GetSamples()
+{
+    while( fSamplesNb < fCount )
     {
         if( !fRawBuffer )
         {
-            if( !( fRawBuffer = Pop( fAudio->fRawFifo ) ) )
+            if( !( fRawBuffer = fAudio->fRawFifo->Pop() ) )
             {
                 return false;
             }
@@ -126,16 +166,16 @@ bool HBMp3Encoder::GetSamples( uint32_t count )
             fPosition    = fRawBuffer->fPosition;
         }
 
-        int willCopy = MIN( count - samplesNb, 6 * 256 - fPosInBuffer );
+        int willCopy = MIN( fCount - fSamplesNb, 6 * 256 - fPosInBuffer );
 
-        memcpy( fLeftSamples + samplesNb,
+        memcpy( fLeftSamples + fSamplesNb,
                 (float*) fRawBuffer->fData + fPosInBuffer,
                 willCopy * sizeof( float ) );
-        memcpy( fRightSamples + samplesNb,
+        memcpy( fRightSamples + fSamplesNb,
                 (float*) fRawBuffer->fData + 6 * 256 + fPosInBuffer,
                 willCopy * sizeof( float ) );
 
-        samplesNb    += willCopy;
+        fSamplesNb    += willCopy;
         fPosInBuffer += willCopy;
 
         if( fPosInBuffer == 6 * 256 )
index 67b8647..fb83489 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Mp3Encoder.h,v 1.5 2003/09/30 14:38:15 titer Exp $
+/* $Id: Mp3Encoder.h,v 1.9 2003/10/07 22:48:31 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -8,27 +8,36 @@
 #define HB_MP3_ENCODER_H
 
 #include "Common.h"
-#include "Thread.h"
 
-class HBMp3Encoder : public HBThread
+class HBMp3Encoder
 {
     public:
                     HBMp3Encoder( HBManager * manager,
                                   HBAudio * audio );
+        bool        Work();
 
     private:
-        void        DoWork();
-        bool        GetSamples( uint32_t count );
+        bool        Lock();
+        void        Unlock();
+        bool        GetSamples();
 
         HBManager * fManager;
         HBAudio   * fAudio;
 
+        HBLock    * fLock;
+        bool        fUsed;
+
         HBBuffer  * fRawBuffer;
         uint32_t    fPosInBuffer;  /* in samples */
+        uint32_t    fSamplesNb;
         float     * fLeftSamples;
         float     * fRightSamples;
 
         float       fPosition;
+        lame_global_flags * fGlobalFlags;
+        bool fInitDone;
+        HBBuffer * fMp3Buffer;
+        uint32_t fCount;
 };
 
 #endif
index 1ba4945..3149931 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Mpeg2Decoder.cpp,v 1.14 2003/09/30 14:38:15 titer Exp $
+/* $Id: Mpeg2Decoder.cpp,v 1.21 2003/10/09 14:21:21 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -14,55 +14,91 @@ extern "C" {
 #include <ffmpeg/avcodec.h>
 
 HBMpeg2Decoder::HBMpeg2Decoder( HBManager * manager, HBTitle * title )
-    : HBThread( "mpeg2decoder" )
 {
-    fManager     = manager;
-    fTitle       = title;
+    fManager = manager;
+    fTitle   = title;
+
+    fLock = new HBLock();
+    fUsed = false;
+    
+    fPass = 42;
+    fRawBuffer = NULL;
+    fRawBufferList = new HBList();
+    fHandle = NULL;
 }
 
-void HBMpeg2Decoder::DoWork()
+bool HBMpeg2Decoder::Work()
 {
-    if( !( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) )
+    fLock->Lock();
+    if( fUsed )
     {
-        return;
+        fLock->Unlock();
+        return true;
     }
+    fUsed = true;
+    fLock->Unlock();
 
-    fPass = fMpeg2Buffer->fPass;
-    Init();
-
-    do
+    bool didSomething = false;
+    
+    for( ;; )
     {
-        while( fSuspend )
+        /* Push decoded buffers */
+        while( ( fRawBuffer =
+                    (HBBuffer*) fRawBufferList->ItemAt( 0 ) ) )
+        {
+            if( fTitle->fRawFifo->Push( fRawBuffer ) )
+            {
+                fRawBufferList->RemoveItem( fRawBuffer );
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        if( fRawBufferList->CountItems() )
         {
-            Snooze( 10000 );
+            break;
+        }
+       
+        /* Get a new buffer to decode */
+        if( !( fMpeg2Buffer = fTitle->fMpeg2Fifo->Pop() ) )
+        {
+            break;
         }
 
+        /* (Re)init if needed */
         if( fMpeg2Buffer->fPass != fPass )
         {
-            Close();
             fPass = fMpeg2Buffer->fPass;
             Init();
         }
 
+        /* Do the job */
         DecodeBuffer();
+
+        didSomething = true;
     }
-    while( ( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) );
+
+    fLock->Lock();
+    fUsed = false;
+    fLock->Unlock();
+
+    return didSomething;
 }
 
 void HBMpeg2Decoder::Init()
 {
+    if( fHandle )
+    {
+        mpeg2_close( fHandle );
+    }
+
     fLateField = false;
 
-    /* Init libmpeg2 */
     fHandle = mpeg2_init();
 }
 
-void HBMpeg2Decoder::Close()
-{
-    /* Close libmpeg2 */
-    mpeg2_close( fHandle );
-}
-
 void HBMpeg2Decoder::DecodeBuffer()
 {
     const mpeg2_info_t * info = mpeg2_info( fHandle );
@@ -83,55 +119,52 @@ void HBMpeg2Decoder::DecodeBuffer()
         else if( ( state == STATE_SLICE || state == STATE_END ) &&
                    info->display_fbuf )
         {
-            HBBuffer * rawBuffer = new HBBuffer( 3 * fTitle->fInWidth *
-                                                 fTitle->fInHeight / 2 );
+            fRawBuffer = new HBBuffer( 3 * fTitle->fInWidth *
+                                       fTitle->fInHeight / 2 );
 
             /* TODO : make libmpeg2 write directly in our buffer */
-            memcpy( rawBuffer->fData,
+            memcpy( fRawBuffer->fData,
                     info->display_fbuf->buf[0],
                     fTitle->fInWidth * fTitle->fInHeight );
-            memcpy( rawBuffer->fData + fTitle->fInWidth *
+            memcpy( fRawBuffer->fData + fTitle->fInWidth *
                         fTitle->fInHeight,
                     info->display_fbuf->buf[1],
                     fTitle->fInWidth * fTitle->fInHeight / 4 );
-            memcpy( rawBuffer->fData + fTitle->fInWidth *
+            memcpy( fRawBuffer->fData + fTitle->fInWidth *
                         fTitle->fInHeight + fTitle->fInWidth *
                         fTitle->fInHeight / 4,
                     info->display_fbuf->buf[2],
                     fTitle->fInWidth * fTitle->fInHeight / 4 );
 
-            rawBuffer->fPosition = fMpeg2Buffer->fPosition;
-            rawBuffer->fPass     = fPass;
+            fRawBuffer->fPosition = fMpeg2Buffer->fPosition;
+            fRawBuffer->fPass     = fMpeg2Buffer->fPass;
+
+            fRawBufferList->AddItem( fRawBuffer );
 
             /* NTSC pulldown kludge */
             if( info->display_picture->nb_fields == 3 )
             {
                 if( fLateField )
                 {
-                    HBBuffer * buffer =
-                        new HBBuffer( rawBuffer->fSize );
-                    buffer->fPosition = rawBuffer->fPosition;
-                    buffer->fPass     = rawBuffer->fPass;
-                    memcpy( buffer->fData, rawBuffer->fData,
-                            buffer->fSize );
-                    Push( fTitle->fRawFifo, buffer );
+                    HBBuffer * pulldownBuffer;
+                    pulldownBuffer = new HBBuffer( fRawBuffer->fSize );
+                    pulldownBuffer->fPosition = fRawBuffer->fPosition;
+                    pulldownBuffer->fPass     = fRawBuffer->fPass;
+                    memcpy( pulldownBuffer->fData, fRawBuffer->fData,
+                            pulldownBuffer->fSize );
+                    fRawBufferList->AddItem( pulldownBuffer );
                 }
                 fLateField = !fLateField;
             }
-
-            /* Send it to the encoder */
-            if( !( Push( fTitle->fRawFifo, rawBuffer ) ) )
-            {
-                break;
-            }
         }
         else if( state == STATE_INVALID )
         {
             /* Shouldn't happen on a DVD */
-            Log( "HBMpeg2Decoder : STATE_INVALID" );
+            Log( "HBMpeg2Decoder: STATE_INVALID" );
         }
     }
 
     delete fMpeg2Buffer;
+    fMpeg2Buffer = NULL;
 }
 
index 2e1a46b..9d1f27f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Mpeg2Decoder.h,v 1.10 2003/09/30 14:38:15 titer Exp $
+/* $Id: Mpeg2Decoder.h,v 1.15 2003/10/09 14:21:21 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -8,25 +8,28 @@
 #define HB_MPEG2_DECODER_H
 
 #include "Common.h"
-#include "Thread.h"
 
-class HBMpeg2Decoder : public HBThread
+class HBMpeg2Decoder
 {
     public:
                      HBMpeg2Decoder( HBManager * manager,
                                      HBTitle * title );
+        bool         Work();
 
     private:
-        void         DoWork();
         void         Init();
-        void         Close();
         void         DecodeBuffer();
 
         HBManager  * fManager;
         HBTitle    * fTitle;
 
+        HBLock     * fLock;
+        bool         fUsed;
+
         uint32_t     fPass;
         HBBuffer   * fMpeg2Buffer;
+        HBBuffer   * fRawBuffer;
+        HBList     * fRawBufferList;
         mpeg2dec_t * fHandle;
         bool         fLateField;
 };
index 42fb38b..4ef0a4c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Mpeg4Encoder.cpp,v 1.15 2003/09/30 14:38:15 titer Exp $
+/* $Id: Mpeg4Encoder.cpp,v 1.23 2003/10/09 13:24:48 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
 #include <ffmpeg/avcodec.h>
 
 HBMpeg4Encoder::HBMpeg4Encoder( HBManager * manager, HBTitle * title )
-    : HBThread( "mpeg4encoder" )
 {
     fManager = manager;
     fTitle   = title;
+
+    fLock = new HBLock();
+    fUsed = false;
+
+    fPass = 42;
+    fMpeg4Buffer = NULL;
+    fFile = NULL;
+    fFrame = avcodec_alloc_frame();
+    fLog = NULL;
 }
 
-void HBMpeg4Encoder::DoWork()
+bool HBMpeg4Encoder::Work()
 {
-    if( !( fResizedBuffer = Pop( fTitle->fResizedFifo ) ) )
+    if( !Lock() )
     {
-        return;
+        return false;
     }
 
-    fPass = fResizedBuffer->fPass;
-    Init();
+    bool didSomething = false;
 
-    do
+    for( ;; )
     {
-        while( fSuspend )
+        if( fMpeg4Buffer )
         {
-            Snooze( 10000 );
+            if( fTitle->fMpeg4Fifo->Push( fMpeg4Buffer ) )
+            {
+                fMpeg4Buffer = NULL;
+            }
+            else
+            {
+                break;
+            }
+        }
+    
+        if( !( fResizedBuffer = fTitle->fResizedFifo->Pop() ) )
+        {
+            break;
         }
 
         if( fResizedBuffer->fPass != fPass )
         {
-            Close();
             fPass = fResizedBuffer->fPass;
             Init();
         }
 
         fManager->SetPosition( fResizedBuffer->fPosition );
         EncodeBuffer();
+
+        didSomething = true;
+    }
+
+    Unlock();
+    return didSomething;
+}
+
+bool HBMpeg4Encoder::Lock()
+{
+    fLock->Lock();
+    if( fUsed )
+    {
+        fLock->Unlock();
+        return false;
     }
-    while( ( fResizedBuffer = Pop( fTitle->fResizedFifo ) ) );
+    fUsed = true;
+    fLock->Unlock();
+    return true;
+}
+
+void HBMpeg4Encoder::Unlock()
+{
+    fLock->Lock();
+    fUsed = false;
+    fLock->Unlock();
 }
 
 void HBMpeg4Encoder::Init()
 {
+    /* Clean up if needed */
+    if( fFile )
+    {
+        fclose( fFile );
+    }
+    
     AVCodec * codec = avcodec_find_encoder( CODEC_ID_MPEG4 );
     if( !codec )
     {
         Log( "HBMpeg4Encoder: avcodec_find_encoder() failed" );
-        fManager->Error();
+        fManager->Error( HB_ERROR_MPEG4_INIT );
         return;
     }
 
@@ -94,19 +142,9 @@ void HBMpeg4Encoder::Init()
     if( avcodec_open( fContext, codec ) < 0 )
     {
         Log( "HBMpeg4Encoder: avcodec_open() failed" );
-        fManager->Error();
+        fManager->Error( HB_ERROR_MPEG4_INIT );
         return;
     }
-
-    fFrame = avcodec_alloc_frame();
-}
-
-void HBMpeg4Encoder::Close()
-{
-    if( fPass == 1 )
-    {
-        fclose( fFile );
-    }
 }
 
 void HBMpeg4Encoder::EncodeBuffer()
@@ -120,31 +158,27 @@ void HBMpeg4Encoder::EncodeBuffer()
     fFrame->linesize[1] = fTitle->fOutWidth / 2;
     fFrame->linesize[2] = fTitle->fOutWidth / 2;
 
-    HBBuffer * mpeg4Buffer;
-    mpeg4Buffer = new HBBuffer( 3 * fTitle->fOutWidth *
+    fMpeg4Buffer = new HBBuffer( 3 * fTitle->fOutWidth *
                                 fTitle->fOutHeight / 2 );
         /* Should be really too much... */
 
-    mpeg4Buffer->fPosition = fResizedBuffer->fPosition;
-    mpeg4Buffer->fSize =
-        avcodec_encode_video( fContext, mpeg4Buffer->fData,
-                              mpeg4Buffer->fAllocSize, fFrame );
-    mpeg4Buffer->fKeyFrame = ( fContext->coded_frame->key_frame != 0 );
-
-    delete fResizedBuffer;
+    fMpeg4Buffer->fPosition = fResizedBuffer->fPosition;
+    fMpeg4Buffer->fSize =
+        avcodec_encode_video( fContext, fMpeg4Buffer->fData,
+                              fMpeg4Buffer->fAllocSize, fFrame );
+    fMpeg4Buffer->fKeyFrame = ( fContext->coded_frame->key_frame != 0 );
 
-    if( fPass == 1 )
+    if( fResizedBuffer->fPass == 1 )
     {
         if( fContext->stats_out )
         {
             fprintf( fFile, "%s", fContext->stats_out );
         }
-        delete mpeg4Buffer;
-    }
-    else
-    {
-        /* Mux it */
-        Push( fTitle->fMpeg4Fifo, mpeg4Buffer );
+        delete fMpeg4Buffer;
+        fMpeg4Buffer = NULL;
     }
+
+    delete fResizedBuffer;
+    fResizedBuffer = NULL;
 }
 
index 1bdb294..3d20f31 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Mpeg4Encoder.h,v 1.8 2003/09/30 14:38:15 titer Exp $
+/* $Id: Mpeg4Encoder.h,v 1.11 2003/10/08 11:56:40 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -8,29 +8,34 @@
 #define HB_MPEG4_ENCODER_H
 
 #include "Common.h"
-#include "Thread.h"
 
-class HBMpeg4Encoder : public HBThread
+class HBMpeg4Encoder
 {
     public:
                     HBMpeg4Encoder( HBManager * manager,
                                     HBTitle * title );
+        bool        Work();
 
     private:
-        void        DoWork();
+        bool        Lock();
+        void        Unlock();
+
         void        Init();
-        void        Close();
         void        EncodeBuffer();
 
         HBManager * fManager;
         HBTitle   * fTitle;
 
+        HBLock    * fLock;
+        bool        fUsed;
+
         uint32_t    fPass;
         HBBuffer  * fResizedBuffer;
         AVCodecContext * fContext;
         AVFrame   * fFrame;
         FILE      * fFile;
         char      * fLog;
+        HBBuffer * fMpeg4Buffer;
 };
 
 #endif
index d3fd6b0..c01647a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: MpegDemux.cpp,v 1.10 2003/10/04 12:12:48 titer Exp $
+/* $Id: MpegDemux.cpp,v 1.18 2003/10/13 15:14:01 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -14,146 +14,176 @@ extern "C" {
 
 HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitle * title,
                           HBAudio * audio1, HBAudio * audio2 )
-    : HBThread( "mpegdemux" )
 {
-    fManager        = manager;
-    fTitle          = title;
-    fAudio1         = audio1;
-    fAudio2         = audio2;
+    fManager = manager;
+    fTitle   = title;
+    fAudio1  = audio1;
+    fAudio2  = audio2;
 
-    fPSBuffer       = NULL;
-    fESBuffer       = NULL;
-    fESBufferList   = NULL;
+    fLock = new HBLock();
+    fUsed = false;
+
+    fPSBuffer      = NULL;
+    fESBuffer      = NULL;
+    fESBufferList  = NULL;
 
     fFirstVideoPTS  = -1;
     fFirstAudio1PTS = -1;
     fFirstAudio2PTS = -1;
 }
 
-void HBMpegDemux::DoWork()
+HBMpegDemux::~HBMpegDemux()
 {
-    for( ;; )
+    /* Free memory */
+    if( fESBufferList )
     {
-        while( fSuspend )
-        {
-            Snooze( 10000 );
-        }
-
-        /* Get a PS packet */
-        if( !( fPSBuffer = Pop( fTitle->fPSFifo ) ) )
+        while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) )
         {
-            break;
+            fESBufferList->RemoveItem( fESBuffer );
+            delete fESBuffer;
         }
+    }
+    delete fLock;
+}
 
-        /* Get the ES data in it */
-        PStoES( fPSBuffer, &fESBufferList );
-
-        if( !fESBufferList )
-        {
-            continue;
-        }
+bool HBMpegDemux::Work()
+{
+    if( !Lock() )
+    {
+        return false;
+    }
+    
+    bool didSomething = false;
 
-        while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) )
+    for( ;; )
+    {
+        /* If we have buffers waiting, try to push them */
+        if( fESBufferList )
         {
-            fESBufferList->RemoveItem( fESBuffer );
-
-            if( fESBuffer->fPass == 1 && fESBuffer->fStreamId != 0xE0 )
+            for( uint32_t i = 0; i < fESBufferList->CountItems(); )
             {
-                delete fESBuffer;
-                continue;
-            }
+                fESBuffer = (HBBuffer*) fESBufferList->ItemAt( i );
+                
+                if( fESBuffer->fPass == 1 && fESBuffer->fStreamId != 0xE0 )
+                {
+                    fESBufferList->RemoveItem( fESBuffer );
+                    delete fESBuffer;
+                    continue;
+                }
 
-            /* Look for a decoder for this ES */
-            if( fESBuffer->fStreamId == 0xE0 )
-            {
-                if( fFirstVideoPTS < 0 )
+                /* Look for a decoder for this ES */
+
+                if( fESBuffer->fStreamId == 0xE0 )
                 {
-                    fFirstVideoPTS = fESBuffer->fPTS;
+                    if( fFirstVideoPTS < 0 )
+                    {
+                        fFirstVideoPTS = fESBuffer->fPTS;
+                        Log( "HBMpegDemux: got first 0xE0 packet (%lld)",
+                             fFirstVideoPTS );
+                    }
+                    if( fTitle->fMpeg2Fifo->Push( fESBuffer ) )
+                    {
+                        fESBufferList->RemoveItem( fESBuffer );
+                    }
+                    else
+                    {
+                        i++;
+                    }
                 }
-                Push( fTitle->fMpeg2Fifo, fESBuffer );
-            }
-            else if( fAudio1 &&
-                     fESBuffer->fStreamId == fAudio1->fId )
-            {
-                /* If the audio track starts later than the video,
-                   repeat the first frame as long as needed  */
-                if( fFirstAudio1PTS < 0 )
+                else if( fAudio1 &&
+                         fESBuffer->fStreamId == fAudio1->fId )
                 {
-                    fFirstAudio1PTS = fESBuffer->fPTS;
+                    if( fFirstAudio1PTS < 0 )
+                    {
+                        fFirstAudio1PTS = fESBuffer->fPTS;
+                        Log( "HBMpegDemux: got first 0x%x packet (%lld)",
+                             fAudio1->fId, fFirstAudio1PTS );
 
-                    if( fFirstAudio1PTS > fFirstVideoPTS )
+                        fAudio1->fDelay =
+                            ( fFirstAudio1PTS - fFirstVideoPTS ) / 90;
+                    }
+                    if( fAudio1->fAc3Fifo->Push( fESBuffer ) )
+                    {
+                        fESBufferList->RemoveItem( fESBuffer );
+                    }
+                    else
                     {
-                        Log( "HBMpegDemux::DoWork() : audio track %x "
-                             "is late (%lld)", fAudio1->fId,
-                             fFirstAudio1PTS - fFirstVideoPTS );
-                        InsertSilence( fFirstAudio1PTS - fFirstVideoPTS,
-                                       fAudio1->fAc3Fifo,
-                                       fESBuffer );
+                        i++;
                     }
                 }
-                Push( fAudio1->fAc3Fifo, fESBuffer );
-            }
-            else if( fAudio2 &&
-                     fESBuffer->fStreamId == fAudio2->fId )
-            {
-                if( fFirstAudio2PTS < 0 )
+                else if( fAudio2 &&
+                         fESBuffer->fStreamId == fAudio2->fId )
                 {
-                    fFirstAudio2PTS = fESBuffer->fPTS;
+                    if( fFirstAudio2PTS < 0 )
+                    {
+                        fFirstAudio2PTS = fESBuffer->fPTS;
+                        Log( "HBMpegDemux: got first 0x%x packet (%lld)",
+                             fAudio2->fId, fFirstAudio2PTS );
 
-                    if( fFirstAudio2PTS > fFirstVideoPTS )
+                        fAudio2->fDelay =
+                            ( fFirstAudio2PTS - fFirstVideoPTS ) / 90;
+                    }
+                    if( fAudio2->fAc3Fifo->Push( fESBuffer ) )
                     {
-                        Log( "HBMpegDemux::DoWork() : audio track %x "
-                             "is late (%lld)", fAudio2->fId,
-                             fFirstAudio2PTS - fFirstVideoPTS );
-                        InsertSilence( fFirstAudio2PTS - fFirstVideoPTS,
-                                       fAudio2->fAc3Fifo,
-                                       fESBuffer );
+                        fESBufferList->RemoveItem( fESBuffer );
                     }
+                    else
+                    {
+                        i++;
+                    }
+                }
+                else
+                {
+                    fESBufferList->RemoveItem( fESBuffer );
+                    delete fESBuffer;
                 }
-                Push( fAudio2->fAc3Fifo, fESBuffer );
+            }
+
+            if( !fESBufferList->CountItems() )
+            {
+                delete fESBufferList;
+                fESBufferList = NULL;
             }
             else
             {
-                delete fESBuffer;
+                break;
             }
         }
-        delete fESBufferList;
-    }
-}
 
-void HBMpegDemux::InsertSilence( int64_t time, HBFifo * fifo,
-                                 HBBuffer * buffer )
-{
-    int        flags      = 0;
-    int        sampleRate = 0;
-    int        bitrate    = 0;
-    int        frameSize  = a52_syncinfo( buffer->fData, &flags,
-                                          &sampleRate, &bitrate );
-
-    if( !frameSize )
-    {
-        Log( "HBMpegDemux::InsertSilence() : a52_syncinfo() failed" );
-        return;
-    }
+        /* Get a PS packet */
+        if( !( fPSBuffer = fTitle->fPSFifo->Pop() ) )
+        {
+            break;
+        }
 
-    uint32_t frames = ( ( sampleRate * time / 90000 ) + ( 3 * 256 ) )
-                          / ( 6 * 256 );
+        /* Get the ES data in it */
+        PStoES( fPSBuffer, &fESBufferList );
 
-    if( !frames )
-    {
-        return;
+        didSomething = true;
     }
 
-    Log( "HBMpegDemux::InsertSilence() : adding %d frames", frames );
+    Unlock();
+    return didSomething;
+}
 
-    HBBuffer * buffer2;
-    for( uint32_t i = 0; i < frames; i++ )
+bool HBMpegDemux::Lock()
+{
+    fLock->Lock();
+    if( fUsed )
     {
-        buffer2 = new HBBuffer( frameSize );
-        buffer2->fPosition = buffer->fPosition;
-        memcpy( buffer2->fData, buffer->fData, frameSize );
-        Push( fifo, buffer2 );
-    }
+        fLock->Unlock();
+        return false;
+    }   
+    fUsed = true;
+    fLock->Unlock();
+    return true;
+}
+
+void HBMpegDemux::Unlock()
+{
+    fLock->Lock();
+    fUsed = false;
+    fLock->Unlock();
 }
 
 bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList )
index ef5b1b3..187a08d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: MpegDemux.h,v 1.6 2003/10/04 12:12:48 titer Exp $
+/* $Id: MpegDemux.h,v 1.11 2003/10/09 13:24:48 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -8,26 +8,29 @@
 #define HB_MPEG_DEMUX_H
 
 #include "Common.h"
-#include "Thread.h"
 
 bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList );
 
-class HBMpegDemux : public HBThread
+class HBMpegDemux
 {
     public:
-                   HBMpegDemux( HBManager * manager, HBTitle * title,
-                                HBAudio * audio1, HBAudio * audio2 );
+                    HBMpegDemux( HBManager * manager, HBTitle * title,
+                                 HBAudio * audio1, HBAudio * audio2 );
+                    ~HBMpegDemux();
+        bool        Work();
 
     private:
-        void        DoWork();
-        void        InsertSilence( int64_t time, HBFifo * fifo,
-                                   HBBuffer * buffer );
+        bool        Lock();
+        void        Unlock();
 
         HBManager * fManager;
         HBTitle   * fTitle;
         HBAudio   * fAudio1;
         HBAudio   * fAudio2;
 
+        HBLock    * fLock;
+        bool        fUsed;
+
         HBBuffer  * fPSBuffer;
         HBBuffer  * fESBuffer;
         HBList    * fESBufferList;
index e3cae39..0b9c794 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Resizer.cpp,v 1.3 2003/09/30 14:38:15 titer Exp $
+/* $Id: Resizer.cpp,v 1.8 2003/10/09 13:24:48 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
 #include <ffmpeg/avcodec.h>
 
 HBResizer::HBResizer( HBManager * manager, HBTitle * title )
-    : HBThread( "resizer" )
 {
-    fManager     = manager;
-    fTitle       = title;
-}
+    fManager = manager;
+    fTitle   = title;
+
+    /* Lock */
+    fLock = new HBLock();
+    fUsed = false;
 
-void HBResizer::DoWork()
-{
     /* Init libavcodec */
-    ImgReSampleContext * resampleContext =
+    fResampleContext =
         img_resample_full_init( fTitle->fOutWidth, fTitle->fOutHeight,
                                 fTitle->fInWidth, fTitle->fInHeight,
                                 fTitle->fTopCrop, fTitle->fBottomCrop,
                                 fTitle->fLeftCrop, fTitle->fRightCrop );
 
     /* Buffers & pictures */
-    HBBuffer * rawBuffer, * deinterlacedBuffer, * resizedBuffer;
-    AVPicture rawPicture, deinterlacedPicture, resizedPicture;
-
-    deinterlacedBuffer = new HBBuffer( 3 * fTitle->fInWidth *
-                                       fTitle->fInHeight / 2 );
-    avpicture_fill( &deinterlacedPicture, deinterlacedBuffer->fData,
+    fRawBuffer           = NULL;
+    fDeinterlacedBuffer  = new HBBuffer( 3 * fTitle->fInWidth *
+                                        fTitle->fInHeight / 2 );
+    fResizedBuffer       = NULL;
+    fRawPicture          = (AVPicture*) malloc( sizeof( AVPicture ) );
+    fDeinterlacedPicture = (AVPicture*) malloc( sizeof( AVPicture ) );
+    fResizedPicture      = (AVPicture*) malloc( sizeof( AVPicture ) );
+
+    avpicture_fill( fDeinterlacedPicture, fDeinterlacedBuffer->fData,
                     PIX_FMT_YUV420P, fTitle->fInWidth,
                     fTitle->fInHeight );
+}
+
+HBResizer::~HBResizer()
+{
+    /* Free memory */
+    free( fResizedPicture );
+    free( fDeinterlacedPicture );
+    free( fRawPicture );
+    if( fResizedBuffer ) delete fResizedBuffer;
+    delete fDeinterlacedBuffer;
+    img_resample_close( fResampleContext );
+    delete fLock;
+}
 
+bool HBResizer::Work()
+{
+    if( !Lock() )
+    {
+        return false;
+    }
+
+    bool didSomething = false;
+    
     for( ;; )
     {
-        while( fSuspend )
+        /* Push the latest resized buffer */
+        if( fResizedBuffer )
         {
-            Snooze( 10000 );
+            if( fTitle->fResizedFifo->Push( fResizedBuffer ) )
+            {
+                fResizedBuffer = NULL;
+            }
+            else
+            {
+                break;
+            }
         }
-
-        if( !( rawBuffer = Pop( fTitle->fRawFifo ) ) )
+        
+        /* Get a new raw picture */
+        if( !( fRawBuffer = fTitle->fRawFifo->Pop() ) )
         {
             break;
         }
 
-        avpicture_fill( &rawPicture, rawBuffer->fData,
+        /* Do the job */
+        avpicture_fill( fRawPicture, fRawBuffer->fData,
                         PIX_FMT_YUV420P, fTitle->fInWidth,
                         fTitle->fInHeight );
 
-        resizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth *
+        fResizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth *
                                       fTitle->fOutHeight / 2 );
-        resizedBuffer->fPosition = rawBuffer->fPosition;
-        resizedBuffer->fPass     = rawBuffer->fPass;
-        avpicture_fill( &resizedPicture, resizedBuffer->fData,
+        fResizedBuffer->fPosition = fRawBuffer->fPosition;
+        fResizedBuffer->fPass     = fRawBuffer->fPass;
+        avpicture_fill( fResizedPicture, fResizedBuffer->fData,
                         PIX_FMT_YUV420P, fTitle->fOutWidth,
                         fTitle->fOutHeight );
 
-
         if( fTitle->fDeinterlace )
         {
-            avpicture_deinterlace( &deinterlacedPicture, &rawPicture,
+            avpicture_deinterlace( fDeinterlacedPicture, fRawPicture,
                                    PIX_FMT_YUV420P,
                                    fTitle->fInWidth,
                                    fTitle->fInHeight );
-            img_resample( resampleContext, &resizedPicture,
-                          &deinterlacedPicture );
+            img_resample( fResampleContext, fResizedPicture,
+                          fDeinterlacedPicture );
         }
         else
         {
-            img_resample( resampleContext, &resizedPicture,
-                          &rawPicture );
+            img_resample( fResampleContext, fResizedPicture,
+                          fRawPicture );
         }
+        delete fRawBuffer;
+        fRawBuffer = NULL;
 
-        Push( fTitle->fResizedFifo, resizedBuffer );
-        delete rawBuffer;
+        didSomething = true;
     }
 
-    /* Free memory */
-    delete deinterlacedBuffer;
+    Unlock();
+    return didSomething;
+}
 
-    /* Close libavcodec */
-    img_resample_close( resampleContext );
+bool HBResizer::Lock()
+{
+    fLock->Lock();
+    if( fUsed )
+    {
+        fLock->Unlock();
+        return false;
+    }
+    fUsed = true;
+    fLock->Unlock();
+    return true;
+}
+
+void HBResizer::Unlock()
+{
+    fLock->Lock();
+    fUsed = false;
+    fLock->Unlock();
 }
 
index 1fdde85..f6d4a45 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Resizer.h,v 1.2 2003/09/30 14:38:15 titer Exp $
+/* $Id: Resizer.h,v 1.5 2003/10/07 22:48:31 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -8,18 +8,31 @@
 #define HB_RESIZER_H
 
 #include "Common.h"
-#include "Thread.h"
 
-class HBResizer : public HBThread
+class HBResizer
 {
     public:
                      HBResizer( HBManager * manager, HBTitle * title );
+                     ~HBResizer();
+        bool         Work();
 
     private:
-        void         DoWork();
-
+        bool         Lock();
+        void         Unlock();
+        
         HBManager  * fManager;
         HBTitle    * fTitle;
+
+        HBLock     * fLock;
+        bool         fUsed;
+
+        ImgReSampleContext * fResampleContext;
+        HBBuffer * fRawBuffer;
+        HBBuffer * fDeinterlacedBuffer;
+        HBBuffer * fResizedBuffer;
+        AVPicture * fRawPicture;
+        AVPicture * fDeinterlacedPicture;
+        AVPicture * fResizedPicture;
 };
 
 #endif
index 575b255..44ff6be 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Scanner.cpp,v 1.18 2003/10/04 12:12:48 titer Exp $
+/* $Id: Scanner.cpp,v 1.23 2003/10/13 14:12:18 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -20,21 +20,23 @@ extern "C" {
 }
 
 HBScanner::HBScanner( HBManager * manager, char * device )
-    : HBThread( "scanner" )
+    : HBThread( "scanner", HB_NORMAL_PRIORITY )
 {
     fManager    = manager;
     fDevice     = strdup( device );
+
+    Run();
 }
 
 void HBScanner::DoWork()
 {
-    Log( "HBScanner::DoWork() : opening device %s", fDevice );
+    Log( "HBScanner: opening device %s", fDevice );
 
     dvdplay_ptr vmg;
     vmg = dvdplay_open( fDevice, NULL, NULL );
     if( !vmg )
     {
-        Log( "HBScanner::DoWork() : dvdplay_open() failed (%s)",
+        Log( "HBScanner: dvdplay_open() failed (%s)",
              fDevice );
         fManager->ScanDone( NULL );
         return;
@@ -50,7 +52,7 @@ void HBScanner::DoWork()
             break;
         }
 
-        Log( "HBScanner::DoWork() : scanning title %d", i + 1 );
+        Log( "HBScanner: scanning title %d", i + 1 );
         fManager->Scanning( fDevice, i + 1 );
 
         title = new HBTitle( fDevice, i + 1 );
@@ -61,12 +63,12 @@ void HBScanner::DoWork()
         }
         else
         {
-            Log( "HBScanner::DoWork() : ignoring title %d", i + 1 );
+            Log( "HBScanner: ignoring title %d", i + 1 );
             delete title;
         }
     }
 
-    Log( "HBScanner::DoWork() : closing device %s", fDevice );
+    Log( "HBScanner: closing device %s", fDevice );
     dvdplay_close( vmg );
 
     fManager->ScanDone( titleList );
@@ -78,7 +80,7 @@ bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg )
 
     /* Length */
     title->fLength = dvdplay_title_time( vmg );
-    Log( "HBScanner::ScanTitle() : title length is %lld seconds",
+    Log( "HBScanner::ScanTitle: title length is %lld seconds",
          title->fLength );
 
     /* Discard titles under 10 seconds */
@@ -101,20 +103,46 @@ bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg )
         }
 
         int id = dvdplay_audio_id( vmg, i );
-        if( id > 0 )
+
+        if( id < 1 )
         {
-            if( ( id & 0xFF ) != 0xBD )
+            continue;
+        }
+
+        if( ( id & 0xFF ) != 0xBD )
+        {
+            Log( "HBScanner::ScanTitle: non-AC3 audio track "
+                 "detected, ignoring" );
+            continue;
+        }
+
+        /* Check if we don't already found an track with the same id */
+        audio = NULL;
+        for( uint32_t j = 0; j < title->fAudioList->CountItems(); j++ )
+        {
+            audio = (HBAudio*) title->fAudioList->ItemAt( j );
+            if( (uint32_t) id == audio->fId )
+            {
+                break;
+            }
+            else
             {
-                Log( "HBScanner::ScanTitle() : non-AC3 audio track "
-                     "detected, ignoring" );
-                continue;
+                audio = NULL;
             }
-            attr = dvdplay_audio_attr( vmg, i );
-            audio = new HBAudio( id, LanguageForCode( attr->lang_code ) );
-            Log( "HBScanner::ScanTitle() : new language (%x, %s)",
-                 id, audio->fDescription );
-            title->fAudioList->AddItem( audio );
         }
+
+        if( audio )
+        {
+            Log( "HBScanner::ScanTitle: discarding duplicate track %x",
+                  id );
+            continue;
+        }
+        
+        attr = dvdplay_audio_attr( vmg, i );
+        audio = new HBAudio( id, LanguageForCode( attr->lang_code ) );
+        Log( "HBScanner::ScanTitle: new language (%x, %s)",
+             id, audio->fDescription );
+        title->fAudioList->AddItem( audio );
     }
 
     /* Discard titles with no audio tracks */
@@ -206,7 +234,7 @@ bool HBScanner::DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i )
                     if( dvdplay_read( vmg, psBuffer->fData, 1 ) != 1 ||
                             !PStoES( psBuffer, &esBufferList ) )
                     {
-                        Log( "HBScanner::DecodeFrame : failed to get "
+                        Log( "HBScanner::DecodeFrame: failed to get "
                              "a valid PS packet" );
                         mpeg2_close( handle );
                         fclose( file );
index 43f058c..8f7e6c9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Thread.cpp,v 1.19 2003/10/01 21:17:17 titer Exp $
+/* $Id: Thread.cpp,v 1.23 2003/10/09 23:33:36 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -34,61 +34,35 @@ HBThread::~HBThread()
     pthread_join( fThread, NULL );
 #endif
 
-    Log( "Thread %d stopped (\"%s\")", fThread, fName );
+    Log( "HBThread: thread %d stopped (\"%s\")", fThread, fName );
     free( fName );
 }
 
-void HBThread::Run()
+void HBThread::Suspend()
 {
-#if defined( SYS_BEOS )
-    fThread = spawn_thread( (int32 (*)(void *)) ThreadFunc,
-                            fName, fPriority, this );
-    resume_thread( fThread );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
-    pthread_create( &fThread, NULL,
-                    (void * (*)(void *)) ThreadFunc, this );
-#if 0
-#if defined( SYS_MACOSX )
-    int    policy;
-    struct sched_param param;
-    memset( &param, 0, sizeof( struct sched_param ) );
-    if( fPriority < 0 )
-    {
-        param.sched_priority = (-1) * fPriority;
-        policy = SCHED_OTHER;
-    }
-    else
-    {
-        param.sched_priority = fPriority;
-        policy = SCHED_RR;
-    }
-    if ( pthread_setschedparam( fThread, policy, &param ) )
-    {
-        Log( "HBThread::Run : couldn't set thread priority" );
-    }
-#endif
-#endif
-#endif
-
-    Log( "Thread %d started (\"%s\")", fThread, fName );
+    fSuspend = true;
 }
 
-void HBThread::Stop()
+void HBThread::Resume()
 {
-    Log( "Stopping thread %d (\"%s\")", fThread, fName );
-
-    fDie     = true;
     fSuspend = false;
 }
 
-void HBThread::Suspend()
+int HBThread::GetPid()
 {
-    fSuspend = true;
+    return fPid;
 }
 
-void HBThread::Resume()
+void HBThread::Run()
 {
-    fSuspend = false;
+#if defined( SYS_BEOS )
+    fThread = spawn_thread( (int32 (*)(void *)) ThreadFunc,
+                            fName, fPriority, this );
+    resume_thread( fThread );
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+    pthread_create( &fThread, NULL,
+                    (void * (*)(void *)) ThreadFunc, this );
+#endif
 }
 
 bool HBThread::Push( HBFifo * fifo, HBBuffer * buffer )
@@ -126,6 +100,21 @@ HBBuffer * HBThread::Pop( HBFifo * fifo )
 
 void HBThread::ThreadFunc( HBThread * _this )
 {
+#if defined( SYS_MACOSX )
+    struct sched_param param;
+    memset( &param, 0, sizeof( struct sched_param ) );
+    param.sched_priority = _this->fPriority;
+    if ( pthread_setschedparam( _this->fThread, SCHED_OTHER, &param ) )
+    {
+        Log( "HBThread: couldn't set thread priority" );
+    }
+#endif
+    
+    _this->fPid = (int) getpid();
+
+    Log( "HBThread: thread %d started (\"%s\")",
+         _this->fThread, _this->fName );
+
     _this->DoWork();
 }
 
index 6afd59f..0a09fab 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Thread.h,v 1.16 2003/10/01 21:17:17 titer Exp $
+/* $Id: Thread.h,v 1.19 2003/10/09 16:03:51 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -13,8 +13,8 @@
 #  define HB_LOW_PRIORITY    5
 #  define HB_NORMAL_PRIORITY 10
 #elif defined( SYS_MACOSX )
-#  define HB_LOW_PRIORITY    (-47)
-#  define HB_NORMAL_PRIORITY (-47) /* FIXME */
+#  define HB_LOW_PRIORITY    0
+#  define HB_NORMAL_PRIORITY 31
 #elif defined( SYS_LINUX )
 /* Actually unused */
 #  define HB_LOW_PRIORITY    0
@@ -27,12 +27,12 @@ class HBThread
                       HBThread( char * name,
                                 int priority = HB_LOW_PRIORITY );
         virtual       ~HBThread();
-        void          Run();
-        void          Stop();
         void          Suspend();
         void          Resume();
+        int           GetPid();
 
     protected:
+        void          Run();
         bool          Push( HBFifo * fifo, HBBuffer * buffer );
         HBBuffer *    Pop( HBFifo * fifo );
 
@@ -51,6 +51,7 @@ class HBThread
 #elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
         pthread_t     fThread;
 #endif
+        int           fPid;
 };
 
 #if defined( SYS_BEOS )
diff --git a/core/Worker.cpp b/core/Worker.cpp
new file mode 100644 (file)
index 0000000..5f13520
--- /dev/null
@@ -0,0 +1,150 @@
+/* $Id: Worker.cpp,v 1.9 2003/10/13 17:59:40 titer Exp $
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://beos.titer.org/handbrake/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#include "Ac3Decoder.h"
+#include "Mp3Encoder.h"
+#include "Mpeg2Decoder.h"
+#include "Mpeg4Encoder.h"
+#include "MpegDemux.h"
+#include "Resizer.h"
+#include "Worker.h"
+
+HBWorker::HBWorker( HBTitle * title, HBAudio * audio1,
+                    HBAudio * audio2 )
+   : HBThread( "worker")
+{
+    fTitle  = title;
+    fAudio1 = audio1;
+    fAudio2 = audio2;
+
+    Run();
+}
+
+void HBWorker::DoWork()
+{
+    bool     didSomething;
+    uint64_t mpegDemux    = 0;
+    uint64_t mpeg2Decoder = 0;
+    uint64_t resizer      = 0;
+    uint64_t mpeg4Encoder = 0;
+    uint64_t ac3Decoder1  = 0;
+    uint64_t mp3Encoder1  = 0;
+    uint64_t ac3Decoder2  = 0;
+    uint64_t mp3Encoder2  = 0;
+    uint64_t tmpDate;
+    
+    while( !fDie )
+    {
+        didSomething = false;
+
+        tmpDate = GetDate();
+        if( fTitle->fMpegDemux->Work() )
+        {
+            mpegDemux += ( GetDate() - tmpDate );
+            didSomething = true;
+        }
+
+        if( fDie ) break;
+
+        tmpDate = GetDate();
+        if( fTitle->fMpeg2Decoder->Work() )
+        {
+            mpeg2Decoder += ( GetDate() - tmpDate );
+            didSomething = true;
+        }
+
+        if( fDie ) break;
+
+        tmpDate = GetDate();
+        if( fTitle->fResizer->Work() )
+        {
+            resizer += ( GetDate() - tmpDate );
+            didSomething = true;
+        }
+        
+        if( fDie ) break;
+
+        tmpDate = GetDate();
+        if( fTitle->fMpeg4Encoder->Work() )
+        {
+            mpeg4Encoder += ( GetDate() - tmpDate );
+            didSomething = true;
+        }
+        
+        if( fDie ) break;
+
+        if( fAudio1 )
+        {
+            tmpDate = GetDate();
+            if( fAudio1->fAc3Decoder->Work() )
+            {
+                ac3Decoder1 += ( GetDate() - tmpDate );
+                didSomething = true;
+            }
+            
+            if( fDie ) break;
+            
+            tmpDate = GetDate();
+            if( fAudio1->fMp3Encoder->Work() )
+            {
+                mp3Encoder1 += ( GetDate() - tmpDate );
+                didSomething = true;
+            }
+
+            if( fDie ) break;
+        }
+
+        if( fAudio2 )
+        {
+            tmpDate = GetDate();
+            if( fAudio2->fAc3Decoder->Work() )
+            {
+                ac3Decoder2 += ( GetDate() - tmpDate );
+                didSomething = true;
+            }
+            
+            if( fDie ) break;
+            
+            tmpDate = GetDate();
+            if( fAudio2->fMp3Encoder->Work() )
+            {
+                mp3Encoder2 += ( GetDate() - tmpDate );
+                didSomething = true;
+            }
+
+            if( fDie ) break;
+        }
+
+        if( !didSomething )
+        {
+            Snooze( 10000 );
+        }
+
+        while( fSuspend )
+        {
+            Snooze( 10000 );
+        }
+    }
+
+    tmpDate = mpegDemux + mpeg2Decoder + resizer + mpeg4Encoder +
+        ac3Decoder1 + mp3Encoder1 + ac3Decoder2 + mp3Encoder2;
+    Log( "HBWorker stopped. CPU utilization:" );
+    Log( "- MPEG demuxer:   %.2f %%", 100 * (float) mpegDemux / tmpDate );
+    Log( "- MPEG-2 decoder: %.2f %%", 100 * (float) mpeg2Decoder / tmpDate );
+    Log( "- Resizer:        %.2f %%", 100 * (float) resizer / tmpDate );
+    Log( "- MPEG-4 encoder: %.2f %%", 100 * (float) mpeg4Encoder / tmpDate );
+    if( fAudio1 )
+    {
+    Log( "- AC3 decoder 1:  %.2f %%", 100 * (float) ac3Decoder1 / tmpDate );
+    Log( "- MP3 encoder 1:  %.2f %%", 100 * (float) mp3Encoder1 / tmpDate );
+    }
+    if( fAudio2 )
+    {
+    Log( "- AC3 decoder 2:  %.2f %%", 100 * (float) ac3Decoder2 / tmpDate );
+    Log( "- MP3 encoder 2:  %.2f %%", 100 * (float) mp3Encoder2 / tmpDate );
+    }
+}
+
diff --git a/core/Worker.h b/core/Worker.h
new file mode 100644 (file)
index 0000000..d2d0324
--- /dev/null
@@ -0,0 +1,27 @@
+/* $Id: Worker.h,v 1.1 2003/10/07 17:40:06 titer Exp $
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://beos.titer.org/handbrake/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_WORKER_H
+#define HB_WORKER_H
+
+#include "Common.h"
+#include "Thread.h"
+
+class HBWorker : public HBThread
+{
+    public:
+                  HBWorker( HBTitle * title, HBAudio * audio1,
+                            HBAudio * audio2 );
+
+    private:
+        void      DoWork();
+        
+        HBTitle * fTitle;
+        HBAudio * fAudio1;
+        HBAudio * fAudio2;
+};
+
+#endif
similarity index 66%
rename from macosx/HBController.h
rename to macosx/Controller.h
index 2e3339c..4759a1d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: HBController.h,v 1.19 2003/10/06 21:13:45 titer Exp $
+/* $Id: Controller.h,v 1.6 2003/10/13 23:09:56 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -6,14 +6,19 @@
 
 #include <Cocoa/Cocoa.h>
 
-#include "Manager.h"
+#include "Common.h"
 #include "PictureGLView.h"
+#include "TargetSizeField.h"
 
 @interface HBController : NSObject
 
 {
+    bool                           fDie;
+    
     IBOutlet NSWindow            * fWindow;
 
+    /* Scan view */
+    uint64_t                       fLastDVDDetection;
     IBOutlet NSView              * fScanView;
     IBOutlet NSMatrix            * fScanMatrix;
     IBOutlet NSPopUpButton       * fDVDPopUp;
     IBOutlet NSProgressIndicator * fScanProgress;
     IBOutlet NSButton            * fScanButton;
 
+    IBOutlet NSView              * fTempView;
+
+    /* Rip view */
     IBOutlet NSView              * fRipView;
+
+    /* Video box */
     IBOutlet NSPopUpButton       * fTitlePopUp;
-    IBOutlet NSPopUpButton       * fAudioPopUp;
-    IBOutlet NSTextField         * fVideoField;
-    IBOutlet NSStepper           * fVideoStepper;
-    IBOutlet NSTextField         * fAudioField;
-    IBOutlet NSStepper           * fAudioStepper;
+    IBOutlet NSPopUpButton       * fVideoCodecPopUp;
+    IBOutlet NSMatrix            * fVideoMatrix;
+    IBOutlet NSTextField         * fCustomBitrateField;
+    IBOutlet HBTargetSizeField   * fTargetSizeField;
     IBOutlet NSButton            * fTwoPassCheck;
     IBOutlet NSButton            * fCropButton;
+
+    /* Audio box */
+    IBOutlet NSPopUpButton       * fLanguagePopUp;
+    IBOutlet NSPopUpButton       * fSecondaryLanguagePopUp;
+    IBOutlet NSPopUpButton       * fAudioCodecPopUp;
+    IBOutlet NSPopUpButton       * fAudioBitratePopUp;
+
+    /* Destination box */
+    IBOutlet NSPopUpButton       * fFileFormatPopUp;
     IBOutlet NSTextField         * fFileField;
-    IBOutlet NSButton            * fRipBrowseButton;
+    IBOutlet NSButton            * fFileBrowseButton;
+
+    /* Bottom */
     IBOutlet NSTextField         * fRipStatusField;
+    IBOutlet NSTextField         * fRipInfoField;
     IBOutlet NSProgressIndicator * fRipProgress;
     IBOutlet NSButton            * fSuspendButton;
     IBOutlet NSButton            * fRipButton;
+
+    /* "Done" alert panel */
     IBOutlet NSPanel             * fDonePanel;
 
+    /* Crop & resize panel */
     IBOutlet NSPanel             * fPicturePanel;
-    IBOutlet PictureGLView       * fPictureGLView;
+    IBOutlet HBPictureGLView     * fPictureGLView;
     IBOutlet NSTextField         * fWidthField;
     IBOutlet NSStepper           * fWidthStepper;
     IBOutlet NSButton            * fDeinterlaceCheck;
     IBOutlet NSTextField         * fInfoField;
     int                            fPicture;
 
-    IBOutlet NSView              * fBlankView;
     HBManager                    * fManager;
     HBList                       * fTitleList;
 }
 
+- (IBAction) ScanMatrixChanged: (id) sender;
 - (IBAction) BrowseDVD: (id) sender;
 - (void)     BrowseDVDDone: (NSOpenPanel *) sheet
     returnCode: (int) returnCode contextInfo: (void *) contextInfo;
 - (IBAction) Scan: (id) sender;
 
+- (IBAction) TitlePopUpChanged: (id) sender;
+- (IBAction) VideoMatrixChanged: (id) sender;
+- (IBAction) AudioPopUpChanged: (id) sender;
 - (IBAction) BrowseFile: (id) sender;
 - (void)     BrowseFileDone: (NSSavePanel *) sheet
     returnCode: (int) returnCode contextInfo: (void *) contextInfo;
 - (IBAction) ShowPicturePanel: (id) sender;
 - (IBAction) ClosePanel: (id) sender;
 - (IBAction) Rip: (id) sender;
+- (void)     OverwriteAlertDone: (NSWindow *) sheet
+    returnCode: (int) returnCode contextInfo: (void *) contextInfo;
+- (void)     _Rip;
 - (IBAction) Cancel: (id) sender;
 - (IBAction) Suspend: (id) sender;
 - (IBAction) Resume: (id) sender;
 
 - (void)     UpdateIntf: (NSTimer *) timer;
 - (void)     DetectDrives;
-- (void)     ScanEnableIntf: (id) sender;
-- (void)     UpdatePopUp: (id) sender;
 
 @end
similarity index 61%
rename from macosx/HBController.mm
rename to macosx/Controller.mm
index f46d022..402d721 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: HBController.mm,v 1.24 2003/10/06 21:13:45 titer Exp $
+/* $Id: Controller.mm,v 1.10 2003/10/13 23:09:56 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -10,7 +10,7 @@
 #include <IOKit/storage/IOMedia.h>
 #include <IOKit/storage/IODVDMedia.h>
 
-#include "HBController.h"
+#include "Controller.h"
 #include "Manager.h"
 
 @implementation HBController
     fManager = new HBManager( true );
 
     /* Update the GUI every 1/10 sec */
+    fDie = false;
     [NSTimer scheduledTimerWithTimeInterval: 0.1
         target: self selector: @selector( UpdateIntf: )
-        userInfo: nil repeats: FALSE];
+        userInfo: nil repeats: YES];
 }
 
 - (NSApplicationTerminateReply) applicationShouldTerminate:
     (NSApplication *) app
 {
     /* Clean up */
+    fDie = true;
     delete fManager;
 
     return NSTerminateNow;
 
 - (void) awakeFromNib
 {
-    [[fScanMatrix cellAtRow: 0 column: 0]
-        setAction: @selector( ScanEnableIntf: )];
-    [[fScanMatrix cellAtRow: 0 column: 0] setTarget: self];
-    [[fScanMatrix cellAtRow: 1 column: 0]
-        setAction: @selector( ScanEnableIntf: )];
-    [[fScanMatrix cellAtRow: 1 column: 0] setTarget: self];
+    [fDVDPopUp removeAllItems];
     [fScanProgress setStyle: NSProgressIndicatorSpinningStyle];
     [fScanProgress setDisplayedWhenStopped: NO];
-    [fRipProgress setIndeterminate: NO];
-    [fTitlePopUp removeAllItems];
-    [fAudioPopUp removeAllItems];
+    [fAudioBitratePopUp removeAllItems];
+    [fAudioBitratePopUp addItemWithTitle: @"32"];
+    [fAudioBitratePopUp addItemWithTitle: @"64"];
+    [fAudioBitratePopUp addItemWithTitle: @"96"];
+    [fAudioBitratePopUp addItemWithTitle: @"128"];
+    [fAudioBitratePopUp addItemWithTitle: @"160"];
+    [fAudioBitratePopUp addItemWithTitle: @"192"];
+    [fAudioBitratePopUp addItemWithTitle: @"224"];
+    [fAudioBitratePopUp addItemWithTitle: @"256"];
+    [fAudioBitratePopUp addItemWithTitle: @"288"];
+    [fAudioBitratePopUp addItemWithTitle: @"320"];
+    [fAudioBitratePopUp selectItemWithTitle: @"128"];
 
     char string[1024]; memset( string, 0, 1024 );
     snprintf( string, 1024, "%s/Desktop/Movie.avi", getenv( "HOME" ) );
     [fWindow center];
 
     /* Detect DVD drives */
+    fLastDVDDetection = GetDate();
     [self DetectDrives];
-    [self ScanEnableIntf: self];
-
-    /* Init a blank view, used in window resizing animation */
-    fBlankView = [[NSView alloc] init];
+    [self ScanMatrixChanged: self];
 }
 
 - (BOOL) windowShouldClose: (id) sender
     }
 }
 
+- (IBAction) VideoMatrixChanged: (id) sender;
+{
+    if( ![fVideoMatrix selectedRow] )
+    {
+        [fCustomBitrateField setEnabled: YES];
+        [fTargetSizeField setEnabled: NO];
+    }
+    else
+    {
+        [fCustomBitrateField setEnabled: NO];
+        [fTargetSizeField setEnabled: YES];
+        [fTargetSizeField UpdateBitrate];
+    }
+}
+
 - (IBAction) BrowseFile: (id) sender
 {
     /* Open a panel to let the user choose and update the text field */
     /* XXX */
     newSize.width  = 762 /*fPicturePanelSize.width*/ +
         title->fOutWidthMax - 720;
-    newSize.height = 754 /*fPicturePanelSize.height*/ +
+    newSize.height = 740 /*fPicturePanelSize.height*/ +
         title->fOutHeightMax - 576;
     [fPicturePanel setContentSize: newSize];
 
-    [NSApp beginSheet: fPicturePanel
-        modalForWindow: fWindow
-        modalDelegate: nil
-        didEndSelector: nil
-        contextInfo: nil];
+    [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
+        modalDelegate: nil didEndSelector: nil contextInfo: nil];
     [NSApp runModalForWindow: fPicturePanel];
     [NSApp endSheet: fPicturePanel];
     [fPicturePanel orderOut: self];
         return;
     }
     
+    if( [fCustomBitrateField intValue] < 256 )
+    {
+        NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops",
+            nil, nil, fWindow, self, nil, nil, nil,
+            @"Video bitrate is too low !" );
+        return;
+    }
+    if( [fCustomBitrateField intValue] > 8192 )
+    {
+        NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops",
+            nil, nil, fWindow, self, nil, nil, nil,
+            @"Video bitrate is too high !" );
+        return;
+    }
+    if( [fLanguagePopUp indexOfSelectedItem] ==
+            [fSecondaryLanguagePopUp indexOfSelectedItem] )
+    {
+        NSBeginCriticalAlertSheet( @"Invalid secondary language",
+            @"Ooops", nil, nil, fWindow, self, nil, nil, nil,
+            @"Do you _really_ want to encode the same audio track twice?" );
+        return;
+    }
+
+    FILE * file;
+    if( ( file = fopen( [[fFileField stringValue] cString], "r" ) ) )
+    {
+        fclose( file );
+        NSBeginCriticalAlertSheet( @"File already exists",
+            @"Nooo", @"Yes, go ahead!", nil, fWindow, self,
+            @selector( OverwriteAlertDone:returnCode:contextInfo: ),
+            nil, nil,
+            [NSString stringWithFormat: @"Do you want to overwrite %s ?",
+                [[fFileField stringValue] cString]] );
+        return;
+    }
+
+    [self _Rip];
+}
+
+- (void) OverwriteAlertDone: (NSWindow *) sheet
+    returnCode: (int) returnCode contextInfo: (void *) contextInfo
+{
+    if( returnCode == NSAlertAlternateReturn )
+    {
+        [self _Rip];
+    }
+}
+
+- (void) _Rip
+{
     /* Get the specified title & audio track(s) */
     HBTitle * title = (HBTitle*)
         fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] );
-    HBAudio * audio = (HBAudio*)
-        title->fAudioList->ItemAt( [fAudioPopUp indexOfSelectedItem] );
+    HBAudio * audio1 = (HBAudio*)
+        title->fAudioList->ItemAt( [fLanguagePopUp indexOfSelectedItem] );
+    HBAudio * audio2 = (HBAudio*)
+        title->fAudioList->ItemAt( [fSecondaryLanguagePopUp
+                                       indexOfSelectedItem] );
 
     /* Use user settings */
-    title->fBitrate    = [fVideoStepper intValue];
-    audio->fOutBitrate = [fAudioStepper intValue];
-    title->fTwoPass    = ( [fTwoPassCheck state] == NSOnState );
+    title->fBitrate     = [fCustomBitrateField intValue];
+    title->fTwoPass     = ( [fTwoPassCheck state] == NSOnState );
+    audio1->fOutBitrate = [[fAudioBitratePopUp titleOfSelectedItem]
+                              intValue];
+    if( audio2 )
+    {
+        audio2->fOutBitrate =
+            [[fAudioBitratePopUp titleOfSelectedItem] intValue];
+    }
 
     /* Let libhb do the job */
-    fManager->StartRip( title, audio, NULL,
+    fManager->StartRip( title, audio1, audio2,
                         (char*) [[fFileField stringValue] cString] );
 }
 
 
 - (void) UpdateIntf: (NSTimer *) timer
 {
+    if( fDie )
+    {
+        [timer invalidate];
+        return;
+    }
+
+    /* Update DVD popup */
+    if( [fWindow contentView] == fScanView &&
+        GetDate() > fLastDVDDetection + 2000000 )
+    {
+        [self DetectDrives];
+        fLastDVDDetection = GetDate();
+    }
+    
     /* Ask libhb about what's happening now */
     if( fManager->NeedUpdate() )
     {
             case HB_MODE_INVALID_VOLUME:
             {
                 [fScanMatrix setEnabled: YES];
-                [self ScanEnableIntf: self];
+                [self ScanMatrixChanged: self];
                 [fScanProgress stopAnimation: self];
                 [fScanButton setEnabled: YES];
 
                 
                 /* Show a temporary empty view while the window
                    resizing animation */
-                [fWindow setContentView: fBlankView ];
+                [fWindow setContentView: fTempView ];
 
                 /* Actually resize it */
                 NSRect newFrame;
                 [fWindow setContentView: fRipView ];
                 [fSuspendButton setEnabled: NO];
                 
+                [fTitlePopUp removeAllItems];
                 HBTitle * title;
                 for( uint32_t i = 0; i < fTitleList->CountItems(); i++ )
                 {
                              title->fLength % 60 );
                     [[fTitlePopUp menu] addItemWithTitle:
                         [NSString stringWithCString: string]
-                        action: @selector( UpdatePopUp: )
-                        keyEquivalent: @""];
+                        action: nil keyEquivalent: @""];
                 }
-                [self UpdatePopUp: self];
+                [self TitlePopUpChanged: self];
                 
                 break;
             }
 
             case HB_MODE_ENCODING:
             {
-                [fTitlePopUp setEnabled: NO];
-                [fAudioPopUp setEnabled: NO];
-                [fVideoField setEnabled: NO];
-                [fVideoStepper setEnabled: NO];
-                [fAudioField setEnabled: NO];
-                [fAudioStepper setEnabled: NO];
-                [fTwoPassCheck setEnabled: NO];
-                [fCropButton setEnabled: NO];
-                [fFileField setEnabled: NO];
-                [fRipBrowseButton setEnabled: NO];
-                [fRipButton setTitle: @"Cancel"];
-                [fSuspendButton setEnabled: YES];
-                [fSuspendButton setTitle: @"Suspend"];
+                [fTitlePopUp             setEnabled: NO];
+                [fVideoCodecPopUp        setEnabled: NO];
+                [fVideoMatrix            setEnabled: NO];
+                [fCustomBitrateField     setEnabled: NO];
+                [fTargetSizeField        setEnabled: NO];
+                [fTwoPassCheck           setEnabled: NO];
+                [fCropButton             setEnabled: NO];
+                [fLanguagePopUp          setEnabled: NO];
+                [fSecondaryLanguagePopUp setEnabled: NO];
+                [fAudioCodecPopUp        setEnabled: NO];
+                [fAudioBitratePopUp      setEnabled: NO];
+                [fFileFormatPopUp        setEnabled: NO];
+                [fFileBrowseButton       setEnabled: NO];
+                [fSuspendButton          setEnabled: YES];
+                [fSuspendButton          setTitle: @"Suspend"];
+                [fRipButton              setTitle: @"Cancel"];
             
                 if( !status.fPosition )
                 {
                 }
                 else
                 {
-                    char string[1024]; memset( string, 0, 1024 );
-                    sprintf( string, "Encoding: %.2f %%, %.2f fps "
-                             "(%02d:%02d:%02d remaining)",
-                             100 * status.fPosition, status.fFrameRate,
+                    char string[1024];
+                    memset( string, 0, 1024 );
+                    sprintf( string, "Encoding: %.2f %%",
+                             100 * status.fPosition );
+                    [fRipStatusField setStringValue:
+                        [NSString stringWithCString: string]];
+                    memset( string, 0, 1024 );
+                    sprintf( string,
+                             "Speed: %.2f fps (%02d:%02d:%02d remaining)",
+                             status.fFrameRate,
                              status.fRemainingTime / 3600,
                              ( status.fRemainingTime % 3600 ) / 60,
                              status.fRemainingTime % 60 );
-                    [fRipStatusField setStringValue:
+                    [fRipInfoField setStringValue:
                         [NSString stringWithCString: string]];
+
                     [fRipProgress setIndeterminate: NO];
                     [fRipProgress setDoubleValue: 100 * status.fPosition];
                 }
             case HB_MODE_SUSPENDED:
             {
                 char string[1024]; memset( string, 0, 1024 );
-                sprintf( string, "Encoding: %.2f %%, %.2f fps (PAUSED)",
-                         100 * status.fPosition, status.fFrameRate) ;
+                sprintf( string, "Encoding: %.2f %% (PAUSED)",
+                         100 * status.fPosition ) ;
                 [fRipStatusField setStringValue:
                     [NSString stringWithCString: string]];
+                [fRipInfoField setStringValue: @""];
                 
                 [fRipProgress setDoubleValue: 100 * status.fPosition];
 
                 break;
             }
 
+            case HB_MODE_STOPPING:
+                [fRipStatusField setStringValue: @"Stopping..."];
+                [fRipInfoField setStringValue: @""];
+                [fRipProgress setIndeterminate: YES];
+                [fRipProgress startAnimation: self];;
+                break;
+
             case HB_MODE_DONE:
             case HB_MODE_CANCELED:
             case HB_MODE_ERROR:
-                [fTitlePopUp setEnabled: YES];
-                [fAudioPopUp setEnabled: YES];
-                [fVideoField setEnabled: YES];
-                [fVideoStepper setEnabled: YES];
-                [fAudioField setEnabled: YES];
-                [fAudioStepper setEnabled: YES];
-                [fTwoPassCheck setEnabled: YES];
-                [fCropButton setEnabled: YES];
-                [fFileField setEnabled: YES];
-                [fRipBrowseButton setEnabled: YES];
-                [fRipButton setEnabled: YES];
-                [fRipButton setTitle: @"Rip"];
-                [fSuspendButton setEnabled: NO];
-                [fSuspendButton setTitle: @"Suspend"];
+                [fRipProgress setIndeterminate: NO];
 
                 if( status.fMode == HB_MODE_DONE )
                 {
-                    [fRipStatusField setStringValue: @"Done." ];
                     [fRipProgress setDoubleValue: 100];
+                    [fRipStatusField setStringValue: @"Done." ];
                     NSBeep();
                     [NSApp requestUserAttention: NSInformationalRequest];
                     [NSApp beginSheet: fDonePanel
-                        modalForWindow: fWindow
-                        modalDelegate: nil
-                        didEndSelector: nil
-                        contextInfo: nil];
+                        modalForWindow: fWindow modalDelegate: nil
+                        didEndSelector: nil contextInfo: nil];
                     [NSApp runModalForWindow: fDonePanel];
                     [NSApp endSheet: fDonePanel];
                     [fDonePanel orderOut: self];
                 }
                 else if( status.fMode == HB_MODE_CANCELED )
                 {
-                    [fRipStatusField setStringValue: @"Canceled." ];
                     [fRipProgress setDoubleValue: 0];
+                    [fRipStatusField setStringValue: @"Canceled." ];
                 }
                 else
                 {
-                    [fRipStatusField setStringValue: @"An error occured." ];
                     [fRipProgress setDoubleValue: 0];
+                    switch( status.fError )
+                    {
+                        case HB_ERROR_A52_SYNC:
+                            [fRipStatusField setStringValue:
+                            @"An error occured (corrupted AC3 data)." ];
+                            break;
+                        case HB_ERROR_AVI_WRITE:
+                            [fRipStatusField setStringValue:
+                            @"An error occured (could not write to file)." ];
+                            break;
+                        case HB_ERROR_DVD_OPEN:
+                            [fRipStatusField setStringValue:
+                            @"An error occured (could not open device)." ];
+                            break;
+                        case HB_ERROR_DVD_READ:
+                            [fRipStatusField setStringValue:
+                            @"An error occured (DVD read failed)." ];
+                            break;
+                        case HB_ERROR_MP3_INIT:
+                            [fRipStatusField setStringValue:
+                            @"An error occured (could not init MP3 encoder)." ];
+                            break;
+                        case HB_ERROR_MP3_ENCODE:
+                            [fRipStatusField setStringValue:
+                            @"An error occured (MP3 encoder failed)." ];
+                            break;
+                        case HB_ERROR_MPEG4_INIT:
+                            [fRipStatusField setStringValue:
+                            @"An error occured (could not init MPEG4 encoder)." ];
+                            break;
+                    }
                 }
 
+                [fRipInfoField setStringValue: @""];
+
+                [fTitlePopUp             setEnabled: YES];
+                [fVideoCodecPopUp        setEnabled: YES];
+                [fVideoMatrix            setEnabled: YES];
+                [fTwoPassCheck           setEnabled: YES];
+                [fCropButton             setEnabled: YES];
+                [fLanguagePopUp          setEnabled: YES];
+                [fSecondaryLanguagePopUp setEnabled: YES];
+                [fAudioCodecPopUp        setEnabled: YES];
+                [fAudioBitratePopUp      setEnabled: YES];
+                [fFileFormatPopUp        setEnabled: YES];
+                [fFileBrowseButton       setEnabled: YES];
+                [fSuspendButton          setEnabled: NO];
+                [fSuspendButton          setTitle: @"Suspend"];
+                [fRipButton              setTitle: @"Rip"];
+
+                [self VideoMatrixChanged: self];
+
                 /* Warn the finder to update itself */
                 [[NSWorkspace sharedWorkspace] noteFileSystemChanged:
                     [fFileField stringValue]];
                 break;
         }
     }
-
-    /* Do it again 1/10 second later */
-    [NSTimer scheduledTimerWithTimeInterval: 0.1
-        target: self selector: @selector( UpdateIntf: )
-        userInfo: nil repeats: FALSE];
 }
 
 - (void) DetectDrives
 {
-    /* Empty the current popup */
-    [fDVDPopUp removeAllItems];
-    
     /* Scan DVD drives (stolen from VLC) */
     io_object_t next_media;
     mach_port_t master_port;
         return;
     }
 
+    NSMutableArray * drivesList;
+    drivesList = [NSMutableArray arrayWithCapacity: 1];
+
     next_media = IOIteratorNext( media_iterator );
     if( next_media != NULL )
     {
                                     sizeof(psz_buf) - dev_path_length,
                                     kCFStringEncodingASCII ) )
             {
-                [[fDVDPopUp menu] addItemWithTitle:
-                    [NSString stringWithCString: psz_buf]
-                    action: nil keyEquivalent: @""];
+                [drivesList addObject:
+                    [NSString stringWithCString: psz_buf]];
             }
 
             CFRelease( str_bsd_path );
     }
 
     IOObjectRelease( media_iterator );
+
+    /* Refresh only if a change occured */
+    if( [drivesList count] == (unsigned) [fDVDPopUp numberOfItems] )
+    {
+        bool isSame = true;
+        for( unsigned i = 0; i < [drivesList count]; i++ )
+        {
+            if( ![[drivesList objectAtIndex: i] isEqualToString:
+                    [fDVDPopUp itemTitleAtIndex: i]] )
+            {
+                isSame = false;
+                break;
+            }
+        }
+        if( isSame )
+        {
+            return;
+        }
+    }
+
+    [fDVDPopUp removeAllItems];
+    for( unsigned i = 0; i < [drivesList count]; i++ )
+    {
+        [[fDVDPopUp menu] addItemWithTitle:
+            [drivesList objectAtIndex: i] action: nil
+            keyEquivalent: @""];
+    }
+    [self ScanMatrixChanged: self];
 }
 
-- (void) ScanEnableIntf: (id) sender
+- (IBAction) ScanMatrixChanged: (id) sender
 {
     if( ![fScanMatrix selectedRow] )
     {
     }
 }
 
-- (void) UpdatePopUp: (id) sender
+- (IBAction) TitlePopUpChanged: (id) sender
 {
     HBTitle * title = (HBTitle*)
         fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] );
 
-    [fAudioPopUp removeAllItems];
+    [fLanguagePopUp removeAllItems];
+    [fSecondaryLanguagePopUp removeAllItems];
     
     HBAudio * audio;
     for( uint32_t i = 0; i < title->fAudioList->CountItems(); i++ )
 
         /* We cannot use NSPopUpButton's addItemWithTitle because
            it checks for duplicate entries */
-        [[fAudioPopUp menu] addItemWithTitle:
+        [[fLanguagePopUp menu] addItemWithTitle:
             [NSString stringWithCString: audio->fDescription]
             action: nil keyEquivalent: @""];
+        [[fSecondaryLanguagePopUp menu] addItemWithTitle:
+            [NSString stringWithCString: audio->fDescription]
+            action: nil keyEquivalent: @""];
+    }
+    [fSecondaryLanguagePopUp addItemWithTitle: @"None"];
+    [fSecondaryLanguagePopUp selectItemWithTitle: @"None"];
+    [fSecondaryLanguagePopUp setEnabled:
+        ( title->fAudioList->CountItems() > 1 )];
+
+    [fTargetSizeField SetHBTitle: title];
+    if( [fVideoMatrix selectedRow] )
+    {
+        [fTargetSizeField UpdateBitrate];
+    }
+}
+
+- (IBAction) AudioPopUpChanged: (id) sender
+{
+    if( [fVideoMatrix selectedRow] )
+    {
+        [fTargetSizeField UpdateBitrate];
     }
 }
 
index ae4f048..5ed7ca9 100644 (file)
Binary files a/macosx/English.lproj/InfoPlist.strings and b/macosx/English.lproj/InfoPlist.strings differ
index df2438f..3842995 100644 (file)
@@ -3,6 +3,7 @@
         {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
         {
             ACTIONS = {
+                AudioPopUpChanged = id; 
                 BrowseDVD = id; 
                 BrowseFile = id; 
                 Cancel = id; 
                 Resume = id; 
                 Rip = id; 
                 Scan = id; 
-                ScanEnableIntf = id; 
+                ScanMatrixChanged = id; 
                 ShowPicturePanel = id; 
                 Suspend = id; 
+                TitlePopUpChanged = id; 
                 UpdatePicture = id; 
-                UpdatePopUp = id; 
+                VideoMatrixChanged = id; 
             }; 
             CLASS = HBController; 
             LANGUAGE = ObjC; 
             OUTLETS = {
-                fAudioField = NSTextField; 
-                fAudioPopUp = NSPopUpButton; 
-                fAudioStepper = NSStepper; 
-                fBlankView = NSView; 
+                fAudioBitratePopUp = NSPopUpButton; 
+                fAudioCodecPopUp = NSPopUpButton; 
                 fBottomField = NSTextField; 
                 fBottomStepper = NSStepper; 
                 fCropButton = NSButton; 
+                fCustomBitrateField = NSTextField; 
                 fDVDFolderField = NSTextField; 
                 fDVDPopUp = NSPopUpButton; 
                 fDeinterlaceCheck = NSButton; 
                 fDonePanel = NSPanel; 
+                fFileBrowseButton = NSButton; 
                 fFileField = NSTextField; 
+                fFileFormatPopUp = NSPopUpButton; 
                 fInfoField = NSTextField; 
+                fLanguagePopUp = NSPopUpButton; 
                 fLeftField = NSTextField; 
                 fLeftStepper = NSStepper; 
-                fPictureGLView = PictureGLView; 
+                fPictureGLView = HBPictureGLView; 
                 fPicturePanel = NSPanel; 
                 fRightField = NSTextField; 
                 fRightStepper = NSStepper; 
-                fRipBrowseButton = NSButton; 
                 fRipButton = NSButton; 
+                fRipInfoField = NSTextField; 
                 fRipProgress = NSProgressIndicator; 
                 fRipStatusField = NSTextField; 
                 fRipView = NSView; 
                 fScanProgress = NSProgressIndicator; 
                 fScanStatusField = NSTextField; 
                 fScanView = NSView; 
+                fSecondaryLanguagePopUp = NSPopUpButton; 
                 fSuspendButton = NSButton; 
+                fTargetSizeField = HBTargetSizeField; 
+                fTempView = NSView; 
                 fTitlePopUp = NSPopUpButton; 
                 fTopField = NSTextField; 
                 fTopStepper = NSStepper; 
                 fTwoPassCheck = NSButton; 
-                fVideoField = NSTextField
-                fVideoStepper = NSStepper
+                fVideoCodecPopUp = NSPopUpButton
+                fVideoMatrix = NSMatrix
                 fWidthField = NSTextField; 
                 fWidthStepper = NSStepper; 
                 fWindow = NSWindow; 
             }; 
             SUPERCLASS = NSObject; 
         }, 
+        {CLASS = HBPictureGLView; LANGUAGE = ObjC; SUPERCLASS = NSOpenGLView; }, 
+        {
+            CLASS = HBTargetSizeField; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {
+                fAudioBitratePopUp = NSPopUpButton; 
+                fBitrateField = NSTextField; 
+                fSecondaryLanguagePopUp = NSPopUpButton; 
+            }; 
+            SUPERCLASS = NSTextField; 
+        }, 
         {CLASS = PictureGLView; LANGUAGE = ObjC; SUPERCLASS = NSOpenGLView; }
     ); 
     IBVersion = 1; 
index 0dbd970..af41a14 100644 (file)
@@ -3,25 +3,29 @@
 <plist version="1.0">
 <dict>
        <key>IBDocumentLocation</key>
-       <string>109 136 381 380 0 0 1440 878 </string>
+       <string>29 16 381 380 0 0 1440 878 </string>
        <key>IBEditorPositions</key>
        <dict>
-               <key>249</key>
-               <string>510 472 420 258 0 0 1440 878 </string>
-               <key>256</key>
-               <string>454 372 420 466 0 0 1440 878 </string>
                <key>29</key>
                <string>407 469 205 44 0 0 1440 878 </string>
+               <key>556</key>
+               <string>510 480 420 244 0 0 1440 878 </string>
+               <key>583</key>
+               <string>648 516 144 171 0 0 1440 878 </string>
+               <key>589</key>
+               <string>510 282 420 586 0 0 1440 878 </string>
        </dict>
        <key>IBFramework Version</key>
        <string>291.0</string>
        <key>IBOpenObjects</key>
        <array>
-               <integer>249</integer>
-               <integer>256</integer>
+               <integer>583</integer>
                <integer>21</integer>
+               <integer>589</integer>
+               <integer>365</integer>
                <integer>434</integer>
                <integer>29</integer>
+               <integer>556</integer>
        </array>
        <key>IBSystem Version</key>
        <string>6R73</string>
index a7849eb..9fe3235 100644 (file)
Binary files a/macosx/English.lproj/MainMenu.nib/objects.nib and b/macosx/English.lproj/MainMenu.nib/objects.nib differ
index b4ea5fe..5f40455 100644 (file)
@@ -17,6 +17,8 @@
                                4DF3C8CC052889CD00A80101,
                                4D85758E052B78E300C39CA9,
                                4D85758F052B78E300C39CA9,
+                               4D358C000534A91300D654EB,
+                               4D358C010534A91300D654EB,
                        );
                        isa = PBXGroup;
                        name = Classes;
                29B97315FDCFA39411CA2CEA = {
                        children = (
                                29B97316FDCFA39411CA2CEA,
+                               4D358C040534AB8100D654EB,
                                4D929FEB0527903D00A80101,
                        );
                        isa = PBXGroup;
        <key>CFBundleExecutable</key>
        <string>HandBrake</string>
        <key>CFBundleGetInfoString</key>
-       <string>HandBrake 0.3 - By Eric Petit &lt;titer@m0k.org&gt;</string>
+       <string>HandBrake 0.4 - By Eric Petit &lt;titer@m0k.org&gt;</string>
        <key>CFBundleIconFile</key>
        <string>HandBrake.icns</string>
        <key>CFBundleIdentifier</key>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>0.3</string>
+       <string>0.4</string>
        <key>CFBundleSignature</key>
        <string>HB##</string>
        <key>CFBundleVersion</key>
-       <string>0.3</string>
+       <string>0.4</string>
        <key>NSMainNibFile</key>
        <string>MainMenu</string>
        <key>NSPrincipalClass</key>
                                4D929FEC0527903D00A80101,
                                4D6615EA05288C2300A80101,
                                4D857591052B78E300C39CA9,
+                               4D358C020534A91300D654EB,
+                               4D358C050534AB8100D654EB,
                        );
                        isa = PBXHeadersBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                29B9732CFDCFA39411CA2CEA,
                                4DF3C8CE052889CD00A80101,
                                4D857590052B78E300C39CA9,
+                               4D358C030534A91300D654EB,
                        );
                        isa = PBXSourcesBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                        settings = {
                        };
                };
+               4D358C000534A91300D654EB = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       path = TargetSizeField.h;
+                       refType = 4;
+               };
+               4D358C010534A91300D654EB = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       path = TargetSizeField.mm;
+                       refType = 4;
+               };
+               4D358C020534A91300D654EB = {
+                       fileRef = 4D358C000534A91300D654EB;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               4D358C030534A91300D654EB = {
+                       fileRef = 4D358C010534A91300D654EB;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               4D358C040534AB8100D654EB = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = Common.h;
+                       path = /Users/titer/HandBrake/core/Common.h;
+                       refType = 0;
+               };
+               4D358C050534AB8100D654EB = {
+                       fileRef = 4D358C040534AB8100D654EB;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
                4D6615EA05288C2300A80101 = {
                        fileRef = 4DF3C8CB052889CD00A80101;
                        isa = PBXBuildFile;
                4DF3C8CB052889CD00A80101 = {
                        fileEncoding = 30;
                        isa = PBXFileReference;
-                       path = HBController.h;
+                       path = Controller.h;
                        refType = 4;
                };
                4DF3C8CC052889CD00A80101 = {
                        fileEncoding = 30;
                        isa = PBXFileReference;
-                       path = HBController.mm;
+                       path = Controller.mm;
                        refType = 4;
                };
                4DF3C8CE052889CD00A80101 = {
index effbf3e..06e5a16 100644 (file)
@@ -4,7 +4,7 @@
 
 #include "Manager.h"
 
-@interface PictureGLView : NSOpenGLView
+@interface HBPictureGLView : NSOpenGLView
 
 {
     HBManager        * fManager;
index 72e5641..79103f6 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "PictureGLView.h"
 
-@implementation PictureGLView
+@implementation HBPictureGLView
 
 - (void) SetManager: (HBManager*) manager
 {
diff --git a/macosx/TargetSizeField.h b/macosx/TargetSizeField.h
new file mode 100644 (file)
index 0000000..12224ca
--- /dev/null
@@ -0,0 +1,23 @@
+/* $Id: TargetSizeField.h,v 1.2 2003/10/09 23:33:36 titer Exp $
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://beos.titer.org/handbrake/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#include <Cocoa/Cocoa.h>
+
+#include "Common.h"
+
+@interface HBTargetSizeField : NSTextField
+
+{
+    HBTitle                * fTitle;
+    IBOutlet NSTextField   * fBitrateField;
+    IBOutlet NSPopUpButton * fSecondaryLanguagePopUp;
+    IBOutlet NSPopUpButton * fAudioBitratePopUp;
+}
+
+- (void) SetHBTitle: (HBTitle *) title;
+- (void) UpdateBitrate;
+
+@end
diff --git a/macosx/TargetSizeField.mm b/macosx/TargetSizeField.mm
new file mode 100644 (file)
index 0000000..0c43701
--- /dev/null
@@ -0,0 +1,64 @@
+/* $Id: TargetSizeField.mm,v 1.4 2003/10/09 23:33:36 titer Exp $
+
+   This file is part of the HandBrake source code.
+   Homepage: <http://beos.titer.org/handbrake/>.
+   It may be used under the terms of the GNU General Public License. */
+
+#include "TargetSizeField.h"
+
+@implementation HBTargetSizeField
+
+- (void) textDidBeginEditing: (NSNotification *) notification
+{
+    [self UpdateBitrate];
+    [super textDidBeginEditing: notification];
+}
+
+- (void) textDidEndEditing: (NSNotification *) notification
+{
+    [self UpdateBitrate];
+    [super textDidEndEditing: notification];
+}
+
+- (void) textDidChange: (NSNotification *) notification
+{
+    [self UpdateBitrate];
+    [super textDidChange: notification];
+}
+
+- (void) SetHBTitle: (HBTitle*) title
+{
+    fTitle = title;
+}
+
+- (void) UpdateBitrate
+{
+    int64_t available;
+    available  = (int64_t) [self intValue] * 1024 * 1024;
+
+    /* AVI headers */
+    available -= 2048;
+
+    /* Video chunk headers (8 bytes / frame)
+       and index (16 bytes / frame) */
+    available -= 24 * fTitle->fLength * fTitle->fRate / fTitle->fScale;
+
+    /* Audio tracks */
+    available -= ( ( [[fSecondaryLanguagePopUp titleOfSelectedItem]
+                       compare: @"None"] == NSOrderedSame ) ? 1 : 2 ) *
+                 ( fTitle->fLength *
+                   [[fAudioBitratePopUp titleOfSelectedItem] intValue] *
+                   128 + 24 * fTitle->fLength * 44100 / 1152 );
+    
+    if( available < 0 )
+    {
+        [fBitrateField setIntValue: 0];
+    }
+    else
+    {
+        [fBitrateField setIntValue:
+            available / ( 128 * fTitle->fLength )];
+    }
+}
+
+@end
index d0d5ec9..4567f74 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Test.cpp,v 1.5 2003/10/05 14:28:40 titer Exp $
+/* $Id: Test.cpp,v 1.8 2003/10/13 10:58:24 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://beos.titer.org/handbrake/>.
@@ -27,6 +27,8 @@ int main( int argc, char ** argv )
     char * device      = NULL;
     char * outputFile  = NULL;
     int    titleIdx    = 1;
+    int    audio1Idx   = 1;
+    int    audio2Idx   = 0;
     bool   twoPass     = false;
     bool   deinterlace = false;
     int    width       = 0;
@@ -34,10 +36,13 @@ int main( int argc, char ** argv )
     int    bottomCrop  = 0;
     int    leftCrop    = 0;
     int    rightCrop   = 0;
+    int    cpuCount    = 0;
+    int    vBitrate    = 1024;
+    int    aBitrate    = 128;
 
     /* Parse command line */
     int c;
-    while( ( c = getopt( argc, argv, "vd:o:t:piw:j:k:l:m:" ) ) != -1 )
+    while( ( c = getopt( argc, argv, "vd:o:t:a:b:piw:j:k:l:m:c:e:f:" ) ) != -1 )
     {
         switch( c )
         {
@@ -57,6 +62,14 @@ int main( int argc, char ** argv )
                 titleIdx = atoi( optarg );
                 break;
 
+            case 'a':
+                audio1Idx = atoi( optarg );
+                break;
+
+            case 'b':
+                audio2Idx = atoi( optarg );
+                break;
+
             case 'p':
                 twoPass = true;
                 break;
@@ -85,6 +98,18 @@ int main( int argc, char ** argv )
                 rightCrop = atoi( optarg );
                 break;
 
+            case 'c':
+                cpuCount = atoi( optarg );
+                break;
+
+            case 'e':
+                vBitrate = atoi( optarg );
+                break;
+
+            case 'f':
+                aBitrate = atoi( optarg );
+                break;
+
             default:
                 break;
         }
@@ -96,20 +121,25 @@ int main( int argc, char ** argv )
         fprintf( stderr,
                  "Syntax: HBTest [options] -d <device> -o <file>\n"
                  "Possible options are :\n"
-                 "    -v                   verbose output\n"
-                 "    -t <value>           select a title (default is 1)\n"
-                 "    -p                   2-pass encoding\n"
-                 "    -i                   deinterlace picture\n"
-                 "    -w                   output width\n"
-                 "    -j <value>           top cropping\n"
-                 "    -k <value>           bottom cropping\n"
-                 "    -l <value>           left cropping\n"
-                 "    -m <value>           right cropping\n" );
+                 "    -v           verbose output\n"
+                 "    -t <value>   select a title (default is 1)\n"
+                 "    -a <value>   primary audio channel (default is 1)\n"
+                 "    -b <value>   secondary audio channel (default is none)\n"
+                 "    -p           2-pass encoding\n"
+                 "    -i           deinterlace picture\n"
+                 "    -w           output width\n"
+                 "    -j <value>   top cropping\n"
+                 "    -k <value>   bottom cropping\n"
+                 "    -l <value>   left cropping\n"
+                 "    -m <value>   right cropping\n"
+                 "    -c <value>   CPU count\n"
+                 "    -e <value>   Video bitrate (default is 1024)\n"
+                 "    -f <value>   Audio bitrate (default is 128)\n" );
         return 1;
     }
 
     /* Create the manager thread */
-    HBManager * manager = new HBManager( debug );
+    HBManager * manager = new HBManager( debug, cpuCount );
 
     /* Tell the manager to scan the specified volume */
     manager->ScanVolumes( device );
@@ -183,10 +213,16 @@ int main( int argc, char ** argv )
                 title->fBottomCrop = bottomCrop;
                 title->fLeftCrop = leftCrop;
                 title->fRightCrop = rightCrop;
+                title->fBitrate = vBitrate;
 
-                HBAudio * audio = (HBAudio*) title->fAudioList->ItemAt( 0 );
+                HBAudio * audio1 =
+                    (HBAudio*) title->fAudioList->ItemAt( audio1Idx - 1 );
+                HBAudio * audio2 =
+                    (HBAudio*) title->fAudioList->ItemAt( audio2Idx - 1 );
+                if( audio1 ) audio1->fOutBitrate = aBitrate;
+                if( audio2 ) audio2->fOutBitrate = aBitrate;
 
-                manager->StartRip( title, audio, NULL, outputFile );
+                manager->StartRip( title, audio1, audio2, outputFile );
                 break;
             }