diff options
author | handbrake <[email protected]> | 2006-01-14 13:21:55 +0000 |
---|---|---|
committer | handbrake <[email protected]> | 2006-01-14 13:21:55 +0000 |
commit | dc8de40de13c3f3e643b980a95ef48ccafb542e3 (patch) | |
tree | 953b97afe7082bbe2ce4247c703a51aa8e29a3c9 | |
parent | 4beb6a8b483c9d84677b21cc271ce315f136335c (diff) |
HandBrake 0.6.0-test1
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@10 b64f7644-9d1e-0410-96f1-a4d463321fa5
121 files changed, 10924 insertions, 5985 deletions
diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..4939f8e87 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,18 @@ +$Id: AUTHORS,v 1.1 2003/12/26 20:19:38 titer Exp $ + +Eric Petit <[email protected]> + + Core (construct, multithreading, BeOS/OS X/Linux ports) + + MPEG demuxer + + MPEG-2 and AC3 decoders (w/ libmpeg2/liba52) + + MPEG-4, MP3 and AAC encoders (w/ libavcodec/libxvidcore/libmp3lame/ + libfaac) + + AVI muxer + + MP4 muxer (w/ libmp4v2) + + BeOS interface + + OS X interface + +Laurent Aimar <[email protected]> + + H264 and Vorbis encoders (w/ libx264/libvorbis) + + OGG/OGM muxer (w/ libogg) + + Gtk2 interface + @@ -0,0 +1,30 @@ +$Id: BUILD,v 1.2 2004/02/13 13:45:50 titer Exp $ + +BUILD file for HandBrake <http://handbrake.m0k.org/> + +Building HandBrake +================== + +Step 1: get jam +=============== + +Jam <http://www.perforce.com/jam/jam.html> is a make replacement. +Get it for your operating system: + + OS X: get <http://handbrake.m0k.org/files/jam-2.5rc3-OSX.zip> and + copy jam to /usr/local/bin/. Do not use the modified jam shipped with + the developer tools (/Developer/Private/jam). + + Debian: `apt-get install jam' +Or get the sources from the link above and compile it yourself. + +Step 2 (optional): set custom compiler flags +============================================ + +If you want to optimize the build for a specific CPU, edit the Jamrules +file and modify the "OPTIM = ..." line by adding the needed flags. + +Step 3: build +============= + +Run `jam'. This will build every library HandBrake requires, then +HandBrake itself. + @@ -1,5 +1,5 @@ HandBrake uses a lot of cool libraries from the GNU/Linux world. Thank -their authors ! +their authors! liba52 authors: Aaron Holtzman @@ -59,6 +59,14 @@ libdvdplay authors: Martin Norb�ck St�phane Borel +libfaac authors: + M. Bakker + Tony Lenox + RageOMatic + thebard + Ivan Dimkovic + Krzysztof Nikiel + libmp3lame authors: Mike Cheng Robert Hegemann @@ -86,6 +94,22 @@ libmp3lame authors: Acy Stapp Roel VdB +libmp4v2 authors: + Dave Mackie + Alix Marchandise-Franquet + Bill May + Massimo Villari + Waqar Mohsin + Richard Chen + Rob Arnold + Howdy Pierce + Steven Schultz + Sean Gilligan + Michael Rossberg + Luis F. Ramirez + Petter Reinholdtsen + libmpeg2 authors: Aaron Holtzman Michel Lespinasse @@ -109,6 +133,15 @@ libmpeg2 authors: Martin Vogt Fredrik Vraalsen +libogg authors: + Christopher Montgomery + +libvorbis authors: + Christopher Montgomery + +libx264 authors: + Laurent Aimar + libxvidcore authors: Christoph Lampert Michael Militzer @@ -1,104 +1,71 @@ -# $Id: Jamfile,v 1.10 2003/11/13 02:09:14 titer Exp $ +# $Id: Jamfile,v 1.39 2004/02/18 17:21:00 titer Exp $ # # This file is part of the HandBrake source code. # Homepage: <http://handbrake.m0k.org/>. # It may be used under the terms of the GNU General Public License. -HB_VERSION = 0.5.2 ; +SubDir TOP ; -# Compilers -CC = gcc ; -C++ = g++ ; -LINK = gcc ; +HB_PACKAGES = ; -# Flags -CCFLAGS = $(CFLAGS) ; -CCFLAGS += -g -Wall -Werror ; -CCFLAGS += -DVERSION=\\\"$(HB_VERSION)\\\" -DSYS_$(OS) ; -C++FLAGS = $(CPPFLAGS) ; -C++FLAGS += -g -Wall -Werror ; -C++FLAGS += -DVERSION=\\\"$(HB_VERSION)\\\" -DSYS_$(OS) ; -LINKFLAGS = $(LDFLAGS) ; -HDRS = core ; - -# Optims -CCFLAGS += -funroll-loops ; -C++FLAGS += -funroll-loops ; -OPTIM = -O3 ; - -# Libs -LINKLIBS = -ldvdplay -ldvdread -ldvdcss -lmpeg2 -lavcodec -la52 - -lmp3lame -lxvidcore ; +# CLI app +ObjectCcFlags test/test.c : -I$(TOP)/core -g -Wall ; +LinkLibraries HBTest : + libhb.a liba52.a libavcodec.a libdvdplay.a libdvdread.a libdvdcss.a + libfaac.a libmp3lame.a libmp4v2.a libmpeg2.a libvorbis.a + libvorbisenc.a libogg.a libx264.a libxvidcore.a ; +Main HBTest : test/test.c ; -# OS specific +# BeOS if $(OS) = BEOS { - CCFLAGS += -Wno-multichar ; - C++FLAGS += -Wno-multichar ; - LINKLIBS += -lbe -ltracker ; -} -else if $(OS) = LINUX -{ - LINKLIBS += -lpthread ; -} -else if $(OS) = MACOSX -{ - CCFLAGS += -no-cpp-precomp ; - C++FLAGS += -no-cpp-precomp ; - LINKFLAGS += -multiply_defined suppress ; - - # needed to clean HandBrake.app - RM = rm -rf ; -} -else if $(OS) = CYGWIN -{ - CCFLAGS += -mno-cygwin ; - C++FLAGS += -mno-cygwin ; - LINKFLAGS += -mno-cygwin ; + SOURCES_BEOS = beos/HBApp.cpp beos/HBWindow.cpp ; + ObjectC++Flags $(SOURCES_BEOS) : + -I$(TOP)/core -I$(TOP)/beos/liblayout -g -Wall ; + LINKLIBS on HandBrake = $(LINKLIBS) -L$(TOP)/lib -llayout -lbe ; + LinkLibraries HandBrake : + libhb.a liba52.a libavcodec.a libdvdplay.a libdvdread.a libdvdcss.a + libfaac.a libmp3lame.a libmp4v2.a libmpeg2.a libvorbis.a + libvorbisenc.a libogg.a libx264.a libxvidcore.a ; + Main HandBrake : $(SOURCES_BEOS) ; } -# Do not remove temporary object files -# There MUST be a cleaner way to do this -actions quietly updated piecemeal together RmTemps -{ -} - -# Build HandBrake.app using Xcode -rule OSXApp +# OS X +if $(OS) = MACOSX { - Clean clean : $(1) macosx/build ; - BuildOSXApp $(1) ; + # Build the app + OSXApp HandBrake.app ; + Depends HandBrake.app : + libhb.a liba52.a libavcodec.a libdvdplay.a libdvdread.a + libdvdcss.a libfaac.a libmp3lame.a libmp4v2.a libmpeg2.a + libvorbis.a libvorbisenc.a libogg.a libx264.a libxvidcore.a ; + Depends all : HandBrake.app ; + + # Package + OSXPackage HandBrake-$(HB_VERSION)-OSX.zip ; + Depends HandBrake-$(HB_VERSION)-OSX.zip : HandBrake.app ; + HB_PACKAGES += HandBrake-$(HB_VERSION)-OSX.zip ; } -actions BuildOSXApp +# GTK2 +if $(OS) = LINUX { - $(RM) HandBrake.app ; - ( cd macosx && xcodebuild ) && cp -r macosx/build/HandBrake.app . ; + SOURCES_GTK2 = gtk2/main.c gtk2/callbacks.c gtk2/interface.c + gtk2/support.c ; + ObjectCcFlags $(SOURCES_GTK2) : + -I$(TOP)/core `pkg-config gtk+-2.0 --cflags` ; + LINKLIBS on gtk2HB = $(LINKLIBS) `pkg-config gtk+-2.0 --libs` ; + LinkLibraries gtk2HB : + libhb.a liba52.a libavcodec.a libdvdplay.a libdvdread.a libdvdcss.a + libfaac.a libmp3lame.a libmp4v2.a libmpeg2.a libvorbis.a + libvorbisenc.a libogg.a libx264.a libxvidcore.a ; + Main gtk2HB : $(SOURCES_GTK2) ; } -Library core/libhb : core/Ac3Dec.c core/AviMux.c - core/Utils.c core/DVDRead.c core/Fifo.c - core/HandBrake.c core/Mp3Enc.c - core/Mpeg2Dec.c core/FfmpegEnc.c - core/MadDec.c core/Scale.c - core/Scan.c core/Thread.c core/Work.c - core/XvidEnc.c core/XvidVbr.c ; - -LinkLibraries HBTest : core/libhb.a ; -Main HBTest : test/test.c ; +# Packages +NotFile package ; +Depends package : $(HB_PACKAGES) ; -if $(OS) = BEOS -{ - LinkLibraries HandBrake : core/libhb.a ; - Main HandBrake : beos/HBApp.cpp beos/MainWindow.cpp - beos/PictureWin.cpp beos/ScanView.cpp - beos/RipView.cpp ; -} - -if $(OS) = MACOSX -{ - OSXApp HandBrake.app ; - Depends HandBrake.app : core/libhb.a ; - Depends all : HandBrake.app ; -} +SubInclude TOP contrib ; +SubInclude TOP core ; diff --git a/Jamrules b/Jamrules new file mode 100644 index 000000000..9fdd02fd6 --- /dev/null +++ b/Jamrules @@ -0,0 +1,126 @@ +# Compilers & flags +CC = gcc ; +C++ = g++ ; +CCFLAGS = $(CFLAGS) ; +C++FLAGS = $(CFLAGS) ; +AS = nasm -f elf ; +LINK = g++ ; +OPTIM = -O3 -funroll-loops ; + +# HandBrake defines +HB_VERSION = 0.6.0-test1 ; +DEFINES = HB_$(OS) HB_VERSION=\\\"$(HB_VERSION)\\\" ; +#DEFINES += HB_NOMMX ; + +# OS-specific +if $(OS) = BEOS +{ + CCFLAGS += -Wno-multichar ; + C++FLAGS += -Wno-multichar ; +} +else if $(OS) = LINUX +{ + LINKLIBS = -lpthread ; +} +else if $(OS) = MACOSX +{ + RM = rm -rf ; +} + +# Contrib* rules: mostly the same than Jambase rules, except +# * Targets aren't cleaned by jam clean (to prevent from deleting +# every contrib library by accident) +# * ContribObject handles *.asm files +# * Temporary *.o files aren't removed +rule ContribObject +{ + MakeLocate $(<) : $(LOCATE_TARGET) ; + SEARCH on $(>) = $(SEARCH_SOURCE) ; + HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; + HDRRULE on $(>) = HdrRule ; + HDRSCAN on $(>) = $(HDRPATTERN) ; + HDRSEARCH on $(>) = + $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ; + HDRGRIST on $(>) = $(HDRGRIST) ; + DEFINES on $(<) += $(DEFINES) ; + switch $(>:S) + { + case .asm : As $(<) : $(>) ; + case .nas : As $(<) : $(>) ; + case .c : Cc $(<) : $(>) ; + case .C : C++ $(<) : $(>) ; + case .cc : C++ $(<) : $(>) ; + case .cpp : C++ $(<) : $(>) ; + case .f : Fortran $(<) : $(>) ; + case .l : Cc $(<) : $(<:S=.c) ; + Lex $(<:S=.c) : $(>) ; + case .s : As $(<) : $(>) ; + case .y : Cc $(<) : $(<:S=$(YACCGEN)) ; + Yacc $(<:S=$(YACCGEN)) : $(>) ; + case * : UserObject $(<) : $(>) ; + } +} +rule ContribObjects +{ + local _i ; + for _i in [ FGristFiles $(<) ] + { + ContribObject $(_i:S=$(SUFOBJ)) : $(_i) ; + Depends obj : $(_i:S=$(SUFOBJ)) ; + } +} +rule ContribLibrary +{ + local _l _s ; + _s = [ FGristFiles $(>:S=$(SUFOBJ)) ] ; + _l = $(<:S=$(SUFLIB)) ; + ContribObjects $(>) ; + Depends obj : $(_s) ; + MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ; + Depends $(_l) : $(_s) ; + Archive $(_l) : $(_s) ; + if $(RANLIB) { Ranlib $(_l) ; } + Depends lib : $(_l) ; +} + +# Custom Library rule: same as ContribLibrary, except 'jam clean' +# removes built objects +rule Library +{ + ContribLibrary $(<) : $(>) ; + Clean clean : [ FGristFiles $(>:S=$(SUFOBJ)) ] ; + Clean clean : $(<:S=$(SUFLIB)) ; +} + +# Build HandBrake.app using Xcode +rule OSXApp +{ + Clean clean : $(1) macosx/build ; + BuildOSXApp $(1) ; +} +actions BuildOSXApp +{ + $(RM) $(1) ; + ( cd macosx && xcodebuild ) && \ + cp -r macosx/build/HandBrake.app $(1) && \ + for i in French German; do \ + ( cd $(1)/Contents/Resources && \ + cp -r English.lproj $i.lproj && \ + cp ../../../macosx/i18n/$i.strings \ + $i.lproj/Localizable.strings ) \ + done ; +} +rule OSXPackage +{ + BuildOSXPackage $(1) ; +} +actions BuildOSXPackage +{ + rm -rf $(1) "HandBrake $(HB_VERSION)" && \ + mkdir "HandBrake $(HB_VERSION)" && \ + cp -r AUTHORS COPYING CREDITS HandBrake.app \ + "HandBrake $(HB_VERSION)" && \ + zip -9 -r $(1) "HandBrake $(HB_VERSION)" && \ + rm -rf "HandBrake $(HB_VERSION)" +} + @@ -1,44 +1,56 @@ -$Id: NEWS,v 1.4 2003/11/09 22:11:06 titer Exp $ +$Id: NEWS,v 1.9 2004/02/18 17:21:00 titer Exp $ + +This is the NEWS file for HandBrake <http://handbrake.m0k.org/> + +Changes between 0.5.2 and 0.6.0 + + .mp4 and .ogm output + + aac and vorbis encoding + + experimental h264 encoding + + gtk2 linux interface + + autocrop + +Changes between 0.5.1 and 0.5.2 + + Bugfixes Changes between 0.5 and 0.5.1 - - 2-pass XviD encoding - - Bugfixes + + 2-pass XviD encoding + + Bugfixes Changes between 0.4 and 0.5 - - Bugfixes, rewrite of large parts of the core - - XviD encoding (1-pass only) + + Bugfixes, rewrite of large parts of the core + + XviD encoding (1-pass only) 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 + + 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 - - Allow 2-pass encoding - - Many internal changes & fixes + + OSX & Linux ports + + Allow 2-pass encoding + + Many internal changes & fixes Changes between 0.1.1 and 0.2 - - Fixed a major bug that made HandBrake probably crash after ~ 15 + + Fixed a major bug that made HandBrake probably crash after ~ 15 minutes encoded - - Fixed a few minor memory leaks + + Fixed a few minor memory leaks Changes between 0.1 and 0.1.1 - - Fixed a stupid bug that prevented to scan volumes correctly if + + Fixed a stupid bug that prevented to scan volumes correctly if FAT/NTFS/etc volumes were mounted Changes between 0.1-alpha2 and 0.1 : - - Automatically detect ripped DVDs on BFS volumes - - Allow picture cropping and resizing - - Allow dual-audio encoding - - Created files are quite compliant now (tested with OSX/Quicktime + + Automatically detect ripped DVDs on BFS volumes + + Allow picture cropping and resizing + + Allow dual-audio encoding + + Created files are quite compliant now (tested with OSX/Quicktime and BSPlayer) - - Better A/V sync with some DVDs + + Better A/V sync with some DVDs Changes between 0.1-alpha and 0.1-alpha2 : - - Show length for each title - - Fixed the screwed-audio bug - - Many bugfixes... + + Show length for each title + + Fixed the screwed-audio bug + + Many bugfixes... First version is 0.1-alpha. @@ -1,21 +1,44 @@ +$Id: TODO,v 1.22 2004/02/13 13:45:50 titer Exp $ + +This is the TODO list for HandBrake <http://handbrake.m0k.org/> +Features to be added are written in no particular order. + - Core - + Should be able to boost the audio volume + + Remove some duplicate code here and here + + Should be able to boost or normalize the audio volume + Allow the intf to preview the latest encoded picture + Finish and test the MPEG audio decoder + More encoding options: B-frames, type of estimation etc etc + Subtitle support + Allow the user to split the file in x parts + AC3 pass-through - + AAC & vorbis encoding support - + mp4 & mkv muxing support + + mkv muxing support + manual aspect ratio + rotate the movie + rip only a few chapters - + network shared processing (using RendezVous) + + network shared processing (using RendezVous?) + + do some DVD buffering so the drive can rest most of the time + + custom framerate + + homemade resampler + + VCD output - All interfaces + Use the DVD name in popup and for the name of the created file + nice 'About...' box with link to homepage & faq + + Add a 'Cancel' button in the crop & scale panel + + nicer, more user-friendly "Open" intf - BeOS interface - + Redo the picture panel + + Redo the picture panel (liblayout?) + + Add warnings (invalid bitrate, file already exists etc) + + i18n + +- Mac OS X interface + + Allow to quit HandBrake when the crop & scale sheet is opened + + Warning when the user quit the app while encoding + + Progress bar in the dock icon + + Send a mail when rip is done + +- Bugs + + OSX - crash when trying to encode a DVD from mounted toast image + + OSX - opengl effects somtimes mess up the picture's brightness diff --git a/beos/HBApp.cpp b/beos/HBApp.cpp index 52afce815..add6259f2 100644 --- a/beos/HBApp.cpp +++ b/beos/HBApp.cpp @@ -1,57 +1,31 @@ -/* $Id: HBApp.cpp,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#include <signal.h> - #include "HBApp.h" -#include "MainWindow.h" - -void SigHandler( int signal ) -{ - /* Ugly way to exit cleanly when hitting Ctrl-C */ - ((HBApp*) be_app)->fWindow->PostMessage( B_QUIT_REQUESTED ); -} +#include "HBWindow.h" int main() { - signal( SIGINT, SigHandler ); - signal( SIGHUP, SigHandler ); - signal( SIGQUIT, SigHandler ); - - /* Run the BApplication */ HBApp * app = new HBApp(); app->Run(); delete app; return 0; } -/* Constructor */ HBApp::HBApp() - : BApplication("application/x-vnd.titer-handbrake" ) + : MApplication( "application/x-vnd.titer-handbrake" ) { - fWindow = new MainWindow(); - fWindow->Show(); + fWindow = new HBWindow(); } void HBApp::MessageReceived( BMessage * message ) { switch( message->what ) { - case B_SAVE_REQUESTED: - fWindow->PostMessage( message ); - break; - default: - BApplication::MessageReceived( message ); + MApplication::MessageReceived( message ); break; } } void HBApp::RefsReceived( BMessage * message ) { - fWindow->PostMessage( message ); } diff --git a/beos/HBApp.h b/beos/HBApp.h index fb5c41c38..75f3fc173 100644 --- a/beos/HBApp.h +++ b/beos/HBApp.h @@ -1,24 +1,20 @@ -/* $Id: HBApp.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - #ifndef HB_HB_APP_H #define HB_HB_APP_H -#include <Application.h> +#include "layout-all.h" -class MainWindow; +class HBWindow; -class HBApp : public BApplication +class HBApp : public MApplication { public: - HBApp(); - void MessageReceived( BMessage * message ); - void RefsReceived( BMessage * message ); + HBApp(); + void MessageReceived( BMessage * message ); + void RefsReceived( BMessage * message ); - MainWindow * fWindow; + private: + HBWindow * fWindow; }; #endif + diff --git a/beos/HBWindow.cpp b/beos/HBWindow.cpp new file mode 100644 index 000000000..4bb51d61f --- /dev/null +++ b/beos/HBWindow.cpp @@ -0,0 +1,283 @@ +#include "HBWindow.h" + +#include <MenuItem.h> +#include <Screen.h> + +#define SCAN_OPEN 'scop' +#define RIP_RIP 'riri' + +static void _Scanning( void * data, int title, int titleCount ) +{ + ((HBWindow*)data)->Scanning( title, titleCount ); +} +static void _ScanDone( void * data, HBList * titleList ) +{ + ((HBWindow*)data)->ScanDone( titleList ); +} +static void _Encoding( void * data, float position, int pass, + int passCount, float frameRate, + float avgFrameRate, int remainingTime ) +{ + ((HBWindow*)data)->Encoding( position, pass, passCount, frameRate, + avgFrameRate, remainingTime ); +} +static void _RipDone( void * data, int result ) +{ + ((HBWindow*)data)->RipDone( result ); +} + +HBWindow::HBWindow() + : MWindow( BRect( 0,0,10,10 ), "HandBrake " HB_VERSION, + B_TITLED_WINDOW, 0 ) +{ + /* Init libhb */ + HBCallbacks callbacks; + callbacks.data = this; + callbacks.scanning = _Scanning; + callbacks.scanDone = _ScanDone; + callbacks.encoding = _Encoding; + callbacks.ripDone = _RipDone; + + fHandle = HBInit( 1, 0 ); + HBSetCallbacks( fHandle, callbacks ); + + fScanView = new HGroup( + new Space( minimax( 10,-1,10,-1 ) ), + new VGroup( + new Space( minimax( -1,10,-1,10 ) ), + new MStringView( "Welcome to HandBrake. Select a DVD to open:" ), + new Space( minimax( -1,5,-1,5 ) ), + new HGroup( + fScanRadio = new MRadioGroup( "Detected volume:", + "DVD Folder:", 0 ), + new VGroup( + fScanDetectedPopup = new MPopup( NULL, + "/Bulk/ANGEL_SEASON2_DISC6", 0 ), + fScanFolderControl = new MTextControl( NULL, NULL ), + 0 ), + 0 ), + fScanBrowseButton = new MButton( "Browse", 12 ), + fScanStatusString = new MStringView( "" ), + fScanProgress = new MProgressBar( this ), + fScanOpenButton = new MButton( "Open", + new BMessage( SCAN_OPEN ) ), + new Space( minimax( -1,10,-1,10000 ) ), + 0 ), + new Space( minimax( 10,-1,10,-1 ) ), + 0 ); + + fScanDetectedPopup->Menu()->ItemAt(0)->SetMarked(true); + fScanProgress->ct_mpm = minimax( 0,12,10000,12 ); + + fRipView = new HGroup( + new Space( minimax( 10,-1,10,-1 ) ), + new VGroup( + new Space( minimax( -1,10,-1,10 ) ), + new MBorder( + M_LABELED_BORDER, 15, "General", + new VGroup( + fRipTitlePopup = new MPopup( "DVD title:", "dummy", 0 ), + new MPopup( "Output format:", + "MP4 file / MPEG-4 video / AAC audio", + "OGM file / MPEG-4 video / Vorbis audio", + "AVI file / MPEG-4 video / MP3 audio", + "AVI file / H264 video / MP3 audio", 0 ), + new MTextControl( "File:", "/boot/home/Desktop/Movie.mp4" ), + new MButton( "Browse" ), + 0 ) + ), + new MBorder( + M_LABELED_BORDER, 15, "Video", + new VGroup( + new MPopup( "MPEG-4 encoder:", "FFmpeg", "XviD", 0 ), + new HGroup( + new MStringView( "Bitrate:" ), + new MRadioGroup( "Custom (kbps)", "Target size (MB)", 0 ), + new VGroup( + new MTextControl( NULL, NULL ), + new MTextControl( NULL, NULL ), + 0 ), + 0 ), + new MSplitter(), + new HGroup( + new MCheckBox( "2-pass encoding" ), + new MButton( "Crop & Scale..." ), + 0 ), + 0 ) + ), + new MBorder( + M_LABELED_BORDER, 15, "Audio", + new VGroup( + fRipLanguage1Popup = new MPopup( "Language 1:", + "dummy", 0 ), + fRipLanguage2Popup = new MPopup( "Language 2 (optional):", + "dummy", 0 ), + fRipBitratePopup = new MPopup( "Bitrate (kbps):", "32", + "64", "96", "128", "160", "192", "224", "256", "288", + "320", 0 ), + 0 ) + ), + new MProgressBar( this ), + new HGroup( + new MButton( "Pause" ), + new MButton( "Rip!", new BMessage( RIP_RIP ) ), + 0 ), + new Space( minimax( -1,10,-1,10 ) ), + 0 ), + new Space( minimax( 10,-1,10,-1 ) ), + 0 ); + + fRipBitratePopup->Menu()->ItemAt(3)->SetMarked( true ); + + fLayers = new LayeredGroup( fScanView, fRipView, 0 ); + AddChild( dynamic_cast<BView*>(fLayers) ); + + /* Center the window */ + BScreen screen; + MoveTo( ( screen.Frame().Width() ) / 2, + ( screen.Frame().Height() ) / 2 ); + + Show(); +} + +bool HBWindow::QuitRequested() +{ + HBClose( &fHandle ); + be_app->PostMessage( B_QUIT_REQUESTED ); + return true; +} + +void HBWindow::MessageReceived( BMessage * message ) +{ + switch( message->what ) + { + case SCAN_OPEN: + Lock(); + /* That's ugly, but there doesn't seem to be another way */ + ((BRadioButton*)fScanRadio->ChildAt(0))->SetEnabled( false ); + ((BRadioButton*)fScanRadio->ChildAt(1))->SetEnabled( false ); + fScanDetectedPopup->SetEnabled( false ); + fScanFolderControl->SetEnabled( false ); + fScanBrowseButton->SetEnabled( false ); + fScanOpenButton->SetEnabled( false ); + fScanStatusString->SetText( "Opening device..." ); + Unlock(); + HBScanDVD( fHandle, + fScanDetectedPopup->Menu()->FindMarked()->Label(), 0 ); + break; + + case RIP_RIP: + { + HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, + fRipTitlePopup->Menu()->IndexOf( + fRipTitlePopup->Menu()->FindMarked() ) ); + title->file = strdup( "/boot/home/Desktop/Movie.mp4" ); + title->twoPass = 0; + title->deinterlace = 0; + title->topCrop = title->autoTopCrop; + title->bottomCrop = title->autoBottomCrop; + title->leftCrop = title->autoLeftCrop; + title->rightCrop = title->autoRightCrop; + title->bitrate = 1024; + title->codec = HB_CODEC_FFMPEG; + title->mux = HB_MUX_MP4; + HBAudio * audio = (HBAudio*) HBListItemAt( + title->audioList, 0 ); + audio->codec = HB_CODEC_AAC; + audio->outBitrate = 128; + HBListAdd( title->ripAudioList, audio ); + HBStartRip( fHandle, title ); + break; + } + + default: + MWindow::MessageReceived( message ); + break; + } +} + +void HBWindow::Scanning( int title, int titleCount ) +{ + Lock(); + char string[1024]; memset( string, 0, 1024 ); + snprintf( string, 1023, "Scanning title %d of %d...", + title, titleCount ); + fScanStatusString->SetText( string ); + fScanProgress->SetValue( (float) title / titleCount ); + Unlock(); +} + +void HBWindow::ScanDone( HBList * titleList ) +{ +#define menu fRipTitlePopup->Menu() + Lock(); + BMenuItem * item; + while( ( item = menu->ItemAt(0) ) ) + { + menu->RemoveItem( item ); + delete item; + } + HBTitle * title; + char label[1024]; + for( int i = 0; i < HBListCount( titleList ); i++ ) + { + memset( label, 0, 1024 ); + title = (HBTitle*) HBListItemAt( titleList, i ); + snprintf( label, 1023, "%d - %02dh%02dm%02ds", title->index, + title->length / 3600, ( title->length % 3600 ) / 60, + title->length % 60 ); + menu->AddItem( new BMenuItem( label, NULL ) ); + } + menu->ItemAt(0)->SetMarked( true ); + fTitleList = titleList; + UpdateLanguages(); + fLayers->ActivateLayer( 1 ); + Unlock(); +#undef menu +} + +void HBWindow::Encoding( float position, int pass, int passCount, + float frameRate, float avgFrameRate, + int remainingTime ) +{ +} + +void HBWindow::RipDone( int result ) +{ +} + +void HBWindow::UpdateLanguages() +{ +#define menu fRipTitlePopup->Menu() + HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, + menu->IndexOf( menu->FindMarked() ) ); +#undef menu + +#define menu1 fRipLanguage1Popup->Menu() +#define menu2 fRipLanguage2Popup->Menu() + BMenuItem * item; + while( ( item = menu1->ItemAt(0) ) ) + { + menu1->RemoveItem( item ); + delete item; + } + while( ( item = menu2->ItemAt(0) ) ) + { + menu2->RemoveItem( item ); + delete item; + } + + HBAudio * audio; + for( int i = 0; i < HBListCount( title->audioList ); i++ ) + { + audio = (HBAudio*) HBListItemAt( title->audioList, i ); + menu1->AddItem( new BMenuItem( audio->language, NULL ) ); + menu2->AddItem( new BMenuItem( audio->language, NULL ) ); + } + menu1->ItemAt(0)->SetMarked( true ); + menu2->AddItem( new BMenuItem( "None", NULL ) ); + menu2->ItemAt( menu2->CountItems() - 1 )->SetMarked( true ); +#undef menu1 +#undef menu2 +} + diff --git a/beos/HBWindow.h b/beos/HBWindow.h new file mode 100644 index 000000000..52ddfbf1b --- /dev/null +++ b/beos/HBWindow.h @@ -0,0 +1,41 @@ +#include "layout-all.h" +#include "HandBrake.h" + +class HBWindow : public MWindow +{ + public: + HBWindow(); + bool QuitRequested(); + void MessageReceived( BMessage * message ); + + void Scanning( int title, int titleCount ); + void ScanDone( HBList * titleList ); + void Encoding( float position, int pass, int passCount, + float frameRate, float avgFrameRate, + int remainingTime ); + void RipDone( int result ); + + private: + void UpdateLanguages(); + + HBHandle * fHandle; + HBList * fTitleList; + + LayeredGroup * fLayers; + + MView * fScanView; + MRadioGroup * fScanRadio; + MPopup * fScanDetectedPopup; + MTextControl * fScanFolderControl; + MButton * fScanBrowseButton; + MStringView * fScanStatusString; + MProgressBar * fScanProgress; + MButton * fScanOpenButton; + + MView * fRipView; + MPopup * fRipTitlePopup; + MPopup * fRipLanguage1Popup; + MPopup * fRipLanguage2Popup; + MPopup * fRipBitratePopup; +}; + diff --git a/beos/MainWindow.cpp b/beos/MainWindow.cpp deleted file mode 100644 index 53ea7fcfe..000000000 --- a/beos/MainWindow.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* $Id: MainWindow.cpp,v 1.4 2003/11/09 21:35:06 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#include <Alert.h> -#include <Application.h> -#include <Screen.h> - -#include "MainWindow.h" -#include "ScanView.h" -#include "RipView.h" - -MainWindow::MainWindow() - : BWindow( BRect( 0,0,10,10 ), "HandBrake " VERSION, B_TITLED_WINDOW, - B_NOT_RESIZABLE | B_NOT_ZOOMABLE ) -{ - fHandle = HBInit( 1, 0 ); - - /* Add the scan view */ - fScanView = new ScanView( fHandle ); - fRipView = new RipView( fHandle ); - 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 MainWindow::QuitRequested() -{ - /* Clean up */ - fDie = true; - long exit_value; - wait_for_thread( fUpdateThread, &exit_value ); - HBClose( &fHandle ); - - /* Stop the application */ - be_app->PostMessage( B_QUIT_REQUESTED ); - return true; -} - -void MainWindow::MessageReceived( BMessage * message ) -{ - switch( message->what ) - { - case B_ABOUT_REQUESTED: - { - BAlert * alert; - alert = new BAlert( "About HandBrake", - "HandBrake " VERSION "\n\n" - "by Eric Petit <[email protected]>\n" - "Homepage : <http://handbrake.m0k.org/>\n\n" - "No, you don't want to know where this stupid app " - "name comes from.\n\n" - "Thanks to BGA for pointing out very cool bugs ;)", - "Woot !" ); - alert->Go( NULL ); - break; - } - - case B_REFS_RECEIVED: - case SCAN_RADIO: - case SCAN_BROWSE_BUTTON: - case SCAN_OPEN: - fScanView->MessageReceived( message ); - break; - - 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; - - default: - BWindow::MessageReceived( message ); - break; - } -} - -void MainWindow::UpdateInterface( MainWindow * _this ) -{ - uint64_t time; - int64_t wait; - - while( !_this->fDie ) - { - /* Update every 0.1 sec */ - time = system_time(); - - _this->_UpdateInterface(); - - wait = 100000 - ( system_time() - time ); - if( wait > 0 ) - { - snooze( wait ); - } - } -} - -void MainWindow::_UpdateInterface() -{ - if( !Lock() ) - { - fprintf( stderr, "Lock() failed\n" ); - return; - } - - int modeChanged; - HBStatus status; - - modeChanged = HBGetStatus( fHandle, &status ); - - switch( status.mode ) - { - case HB_MODE_UNDEF: - case HB_MODE_NEED_DEVICE: - break; - - case HB_MODE_SCANNING: - case HB_MODE_INVALID_DEVICE: - fScanView->UpdateIntf( status, modeChanged ); - break; - - case HB_MODE_READY_TO_RIP: - if( !modeChanged ) - break; - - RemoveChild( fScanView ); - ResizeTo( fRipView->Bounds().Width(), - fRipView->Bounds().Height() ); - AddChild( fRipView ); - fRipView->UpdateIntf( status, modeChanged ); - break; - - case HB_MODE_ENCODING: - case HB_MODE_PAUSED: - case HB_MODE_DONE: - case HB_MODE_CANCELED: - case HB_MODE_ERROR: - fRipView->UpdateIntf( status, modeChanged ); - break; - - default: - break; - } - - Unlock(); -} - diff --git a/beos/MainWindow.h b/beos/MainWindow.h deleted file mode 100644 index 5e50775bc..000000000 --- a/beos/MainWindow.h +++ /dev/null @@ -1,36 +0,0 @@ -/* $Id: MainWindow.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - - -#ifndef HB_MAIN_WINDOW_H -#define HB_MAIN_WINDOW_H - -#include <Window.h> -class ScanView; -class RipView; - -#include "HandBrake.h" - -class MainWindow : public BWindow -{ - public: - MainWindow(); - virtual bool QuitRequested(); - virtual void MessageReceived( BMessage * message ); - - private: - static void UpdateInterface( MainWindow * _this ); - void _UpdateInterface(); - - HBHandle * fHandle; - int fUpdateThread; - volatile bool fDie; - - ScanView * fScanView; - RipView * fRipView; -}; - -#endif diff --git a/beos/PictureWin.cpp b/beos/PictureWin.cpp deleted file mode 100644 index 5667dbc3e..000000000 --- a/beos/PictureWin.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* $Id: PictureWin.cpp,v 1.2 2003/11/06 14:36:54 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#include <Bitmap.h> -#include <Box.h> -#include <Button.h> -#include <CheckBox.h> -#include <Screen.h> -#include <Slider.h> - -#include "PictureWin.h" - -#define UPDATE_BITMAP 'upbi' - -/* Handy way to access HBTitle members */ -#define fInWidth fTitle->inWidth -#define fInHeight fTitle->inHeight -#define fPixelWidth fTitle->pixelWidth -#define fPixelHeight fTitle->pixelHeight -#define fDeinterlace fTitle->deinterlace -#define fOutWidth fTitle->outWidth -#define fOutHeight fTitle->outHeight -#define fOutWidthMax fTitle->outWidthMax -#define fOutHeightMax fTitle->outHeightMax -#define fTopCrop fTitle->topCrop -#define fBottomCrop fTitle->bottomCrop -#define fLeftCrop fTitle->leftCrop -#define fRightCrop fTitle->rightCrop - -HBPictureView::HBPictureView( BRect rect, BBitmap * bitmap ) - : BView( rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW ) -{ - fBitmap = bitmap; -} - -void HBPictureView::Draw( BRect rect ) -{ - if( LockLooper() ) - { - DrawBitmap( fBitmap, Bounds() ); - UnlockLooper(); - } - else - { - fprintf( stderr, "LockLooper() failed\n" ); - } - - BView::Draw( rect ); -} - - -/* Constructor */ -HBPictureWin::HBPictureWin( HBHandle * handle, HBTitle * title ) - : BWindow( BRect( 0, 0, 0, 0 ), "Picture settings", - B_FLOATING_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, - B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_NOT_CLOSABLE ) -{ - fHandle = handle; - fTitle = title; - - /* Resize & center */ - ResizeTo( fOutWidthMax + 40, fOutHeightMax + 280 ); - BScreen screen; - MoveTo( ( screen.Frame().Width() - Frame().Width() ) / 2, - ( screen.Frame().Height() - Frame().Height() ) / 2 ); - - /* Build the GUI */ - 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 ) ); - AddChild( view ); - - /* First box : picture + slider */ - r = BRect( 10, 10, fOutWidthMax + 31, fOutHeightMax + 60 ); - BBox * pictureBox; - pictureBox = new BBox( r, NULL ); - pictureBox->SetLabel( "Preview" ); - - /* Leave a one-pixel margin to draw the white line around the picture */ - fBitmap = new BBitmap( BRect( 0, 0, fOutWidthMax + 1, - fOutHeightMax + 1 ), 0, B_RGB32 ); - - /* Picture view */ - r = BRect( 10, 15, fOutWidthMax + 11, fOutHeightMax + 16 ); - fPictureView = new HBPictureView( r, fBitmap ); - pictureBox->AddChild( fPictureView ); - - /* Slider */ - r = BRect( 10, fOutHeightMax + 25, fOutWidthMax + 11, - fOutHeightMax + 55 ); - fPictureSlider = new BSlider( r, NULL, NULL, - new BMessage( UPDATE_BITMAP ), 0, 9 ); - pictureBox->AddChild( fPictureSlider ); - - view->AddChild( pictureBox ); - - /* Second box : scale & crop settings */ - r = BRect( 10, fOutHeightMax + 75, fOutWidthMax + 31, - fOutHeightMax + 235 ); - BBox * settingsBox; - settingsBox = new BBox( r, NULL ); - settingsBox->SetLabel( "Settings" ); - - r = BRect( 10, 15, fOutWidthMax + 11, 30 ); - fDeinterlaceCheck = new BCheckBox( r, NULL, "Deinterlace", - new BMessage( UPDATE_BITMAP ) ); - fDeinterlaceCheck->SetValue( fDeinterlace ? 1 : 0 ); - settingsBox->AddChild( fDeinterlaceCheck ); - - r = BRect( 10, 40, fOutWidthMax + 11, 70 ); - fWidthSlider = new BSlider( r, NULL, "Picture size", - new BMessage( UPDATE_BITMAP ), - 1, fOutWidthMax / 16, - B_TRIANGLE_THUMB ); - fWidthSlider->SetValue( fOutWidth / 16 ); - settingsBox->AddChild( fWidthSlider ); - - r = BRect( 10, 80, ( fOutWidthMax / 2 ) + 5, 110 ); - fTopCropSlider = new BSlider( r, NULL, "Top cropping", - new BMessage( UPDATE_BITMAP ), - 0, fInHeight / 4, - B_TRIANGLE_THUMB ); - fTopCropSlider->SetValue( fTopCrop / 2 ); - settingsBox->AddChild( fTopCropSlider ); - - r = BRect( ( fOutWidthMax / 2 ) + 15, 80, fOutWidthMax + 11, 110 ); - fBottomCropSlider = new BSlider( r, NULL, "Bottom cropping", - new BMessage( UPDATE_BITMAP ), - 0, fInHeight / 4, - B_TRIANGLE_THUMB ); - fBottomCropSlider->SetValue( fBottomCrop / 2 ); - settingsBox->AddChild( fBottomCropSlider ); - - r = BRect( 10, 120, ( fOutWidthMax / 2 ) + 5, 150 ); - fLeftCropSlider = new BSlider( r, NULL, "Left cropping", - new BMessage( UPDATE_BITMAP ), - 0, fInWidth / 4, - B_TRIANGLE_THUMB ); - fLeftCropSlider->SetValue( fLeftCrop / 2 ); - settingsBox->AddChild( fLeftCropSlider ); - - r = BRect( ( fOutWidthMax / 2 ) + 15, 120, fOutWidthMax + 11, 150 ); - fRightCropSlider = new BSlider( r, NULL, "Right cropping", - new BMessage( UPDATE_BITMAP ), - 0, fInWidth / 4, - B_TRIANGLE_THUMB ); - fRightCropSlider->SetValue( fRightCrop / 2 ); - settingsBox->AddChild( fRightCropSlider ); - - view->AddChild( settingsBox ); - - /* "Close" button */ - r = BRect( fOutWidthMax - 49, fOutHeightMax + 245, - fOutWidthMax + 31, fOutHeightMax + 270 ); - BButton * button = new BButton( r, NULL, "OK", - new BMessage( B_QUIT_REQUESTED ) ); - view->AddChild( button ); - - UpdateBitmap( 0 ); -} - -void HBPictureWin::MessageReceived( BMessage * message ) -{ - switch( message->what ) - { - case UPDATE_BITMAP: - UpdateBitmap( fPictureSlider->Value() ); - fPictureView->Draw( fPictureView->Bounds() ); - break; - - default: - BWindow::MessageReceived( message ); - } -} - -void HBPictureWin::UpdateBitmap( int image ) -{ - fOutWidth = 16 * fWidthSlider->Value(); - fTopCrop = 2 * fTopCropSlider->Value(); - fBottomCrop = 2 * fBottomCropSlider->Value(); - fLeftCrop = 2 * fLeftCropSlider->Value(); - fRightCrop = 2 * fRightCropSlider->Value(); - fDeinterlace = ( fDeinterlaceCheck->Value() != 0 ); - - uint8_t * preview = HBGetPreview( fHandle, fTitle, image ); - for( int i = 0; i < fOutHeightMax + 2; i++ ) - { - memcpy( ((uint8_t*) fBitmap->Bits()) + - i * fBitmap->BytesPerRow(), - preview + 4 * ( fOutWidthMax + 2 ) * i, - 4 * ( fOutWidthMax + 2 ) ); - } - free( preview ); - - if( !Lock() ) - { - fprintf( stderr, "Lock() failed\n" ); - return; - } - - char label[128]; - - memset( label, 0, 128 ); - snprintf( label, 128, "Picture size : %d x %d", - fOutWidth, fOutHeight ); - fWidthSlider->SetValue( fOutWidth / 16 ); - fWidthSlider->SetLabel( label ); - - memset( label, 0, 128 ); - snprintf( label, 128, "Top cropping : %d", fTopCrop ); - fTopCropSlider->SetLabel( label ); - - memset( label, 0, 128 ); - snprintf( label, 128, "Bottom cropping : %d", fBottomCrop ); - fBottomCropSlider->SetLabel( label ); - - memset( label, 0, 128 ); - snprintf( label, 128, "Left cropping : %d", fLeftCrop ); - fLeftCropSlider->SetLabel( label ); - - memset( label, 0, 128 ); - snprintf( label, 128, "Right cropping : %d", fRightCrop ); - fRightCropSlider->SetLabel( label ); - - Unlock(); -} diff --git a/beos/PictureWin.h b/beos/PictureWin.h deleted file mode 100644 index 265eb8ad0..000000000 --- a/beos/PictureWin.h +++ /dev/null @@ -1,52 +0,0 @@ -/* $Id: PictureWin.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_PICTURE_WIN_H -#define HB_PICTURE_WIN_H - -#include <View.h> -#include <Window.h> -class BSlider; -class BCheckBox; - -#include "HandBrake.h" - -class HBPictureView : public BView -{ - public: - HBPictureView::HBPictureView( BRect rect, BBitmap * bitmap ); - virtual void Draw( BRect rect ); - - private: - BBitmap * fBitmap; -}; - -class HBPictureWin : public BWindow -{ - public: - HBPictureWin( HBHandle * handle, HBTitle * title ); - virtual void MessageReceived( BMessage * message ); - - void UpdateBitmap( int which ); - - - private: - HBHandle * fHandle; - HBTitle * fTitle; - - /* GUI */ - HBPictureView * fPictureView; - BSlider * fPictureSlider; - BBitmap * fBitmap; - BSlider * fWidthSlider; - BSlider * fTopCropSlider; - BSlider * fBottomCropSlider; - BSlider * fLeftCropSlider; - BSlider * fRightCropSlider; - BCheckBox * fDeinterlaceCheck; -}; - -#endif diff --git a/beos/RipView.cpp b/beos/RipView.cpp deleted file mode 100644 index 0d1e787ab..000000000 --- a/beos/RipView.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/* $Id: RipView.cpp,v 1.4 2003/11/09 21:35:06 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - 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" - -#define DEFAULT_FILE "/boot/home/Desktop/Movie.avi" - -RipView::RipView( HBHandle * handle ) - : BView( BRect( 0,0,400,480 ), NULL, B_FOLLOW_ALL, B_WILL_DRAW ) -{ - fHandle = handle; - - 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 & Scale...", - 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 (Ffmpeg)", NULL ) ); - fVideoCodecPopUp->AddItem( new BMenuItem( "MPEG-4 (XviD)", 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*) HBListItemAt( fTitleList, 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( int i = 0; i < HBListCountItems( title->audioList ); i++ ) - { - audio = (HBAudio*) HBListItemAt( title->audioList, i ); - fLanguagePopUp->AddItem( - new BMenuItem( audio->language, NULL ) ); - fSecondaryLanguagePopUp->AddItem( - new BMenuItem( audio->language, - 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( - ( HBListCountItems( title->audioList ) > 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*) HBListItemAt( fTitleList, 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->length * title->rate / - title->rateBase; - - /* Audio tracks */ - available -= - ( strcmp( fSecondaryLanguagePopUp->FindMarked()->Label(), - "None" ) ? 2 : 1 ) * - ( title->length * - atoi( fAudioBitratePopUp->FindMarked()->Label() ) * 128 + - 24 * title->length * 44100 / 1152 ); - - char string[1024]; memset( string, 0, 1024 ); - if( available < 0 ) - { - sprintf( string, "0" ); - } - else - { - sprintf( string, "%lld", available / - ( 128 * title->length ) ); - } - fCustomBitrateControl->SetText( string ); - break; - } - - case RIP_CROP_BUTTON: - { - int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); - HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, index ); - - HBPictureWin * win; - win = new HBPictureWin( fHandle, 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" ) ) - { - HBResumeRip( fHandle ); - } - else - { - HBPauseRip( fHandle ); - } - - break; - } - - case RIP_RIP_BUTTON: - { - if( strcmp( fStartButton->Label(), "Rip !" ) ) - { - HBStopRip( fHandle ); - } - else - { - int index; - - /* Get asked title & languages */ - index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); - HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, index ); - index = fLanguagePopUp->IndexOf( fLanguagePopUp->FindMarked() ); - HBAudio * audio1 = - (HBAudio*) HBListItemAt( title->audioList, index ); - index = fSecondaryLanguagePopUp->IndexOf( - fSecondaryLanguagePopUp->FindMarked() ); - HBAudio * audio2 = - (HBAudio*) HBListItemAt( title->audioList, index ); - - /* Use user settings */ - title->file = strdup( fFileControl->Text() ); - title->bitrate = atoi( fCustomBitrateControl->Text() ); - title->twoPass = ( fTwoPassCheck->Value() != 0 ); - title->codec = fVideoCodecPopUp->IndexOf( - fVideoCodecPopUp->FindMarked() ) ? HB_CODEC_XVID : - HB_CODEC_FFMPEG; - audio1->outBitrate = - atoi( fAudioBitratePopUp->FindMarked()->Label() ); - if( audio2 ) - { - audio2->outBitrate = - atoi( fAudioBitratePopUp->FindMarked()->Label() ); - } - - /* Let libhb do the job */ - HBStartRip( fHandle, title, audio1, audio2 ); - } - break; - } - - default: - BView::MessageReceived( message ); - break; - } -} - -void RipView::UpdateIntf( HBStatus status, int modeChanged ) -{ - switch( status.mode ) - { - case HB_MODE_READY_TO_RIP: - { - if( !modeChanged ) - break; - - fTitleList = status.titleList; - - HBTitle * title; - for( int i = 0; i < HBListCountItems( fTitleList ); i++ ) - { - title = (HBTitle*) HBListItemAt( fTitleList, i ); - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "%d - %02dh%02dm%02ds", - title->index, title->length / 3600, - ( title->length % 3600 ) / 60, - title->length % 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: - { - if( modeChanged ) - { - 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 ); - fSuspendButton->SetLabel( "Suspend" ); - fSuspendButton->SetEnabled( true ); - fStartButton->SetLabel( "Cancel" ); - fStartButton->SetEnabled( true ); - } - - if( !status.position ) - { - fStatusBar->Update( - fStatusBar->CurrentValue(), - "Starting..." ); - } - else - { - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "Encoding: %.2f %% (%.2f fps, " - "%02dh%02dm%02ds remaining)", - 100 * status.position, - status.frameRate, - status.remainingTime / 3600, - ( status.remainingTime % 3600 ) / 60, - status.remainingTime % 60 ); - fStatusBar->Update( 100 * status.position - - fStatusBar->CurrentValue(), - string ); - } - break; - } - - case HB_MODE_PAUSED: - { - if( modeChanged ) - { - 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 ); - fSuspendButton->SetLabel( "Resume" ); - fSuspendButton->SetEnabled( true ); - fStartButton->SetLabel( "Cancel" ); - fStartButton->SetEnabled( true ); - } - - fStatusBar->Update( 100 * status.position - - fStatusBar->CurrentValue(), "Suspended" ); - break; - } - - case HB_MODE_STOPPING: - { - if( modeChanged ) - { - 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 ); - fSuspendButton->SetLabel( "Suspend" ); - fSuspendButton->SetEnabled( false ); - fStartButton->SetLabel( "Cancel" ); - fStartButton->SetEnabled( false ); - } - - fStatusBar->Update( - fStatusBar->CurrentValue(), - "Stopping..." ); - break; - } - - case HB_MODE_DONE: - { - if( modeChanged ) - { - 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 ); - - fSuspendButton->SetLabel( "Suspend" ); - fSuspendButton->SetEnabled( false ); - fStartButton->SetLabel( "Rip !" ); - fStartButton->SetEnabled( true ); - } - - fStatusBar->Update( 100.0 - fStatusBar->CurrentValue(), - "Done." ); - break; - } - - case HB_MODE_CANCELED: - { - if( modeChanged ) - { - 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 ); - fSuspendButton->SetLabel( "Suspend" ); - fSuspendButton->SetEnabled( false ); - fStartButton->SetLabel( "Rip !" ); - fStartButton->SetEnabled( true ); - } - - fStatusBar->Update( - fStatusBar->CurrentValue(), - "Canceled." ); - break; - } - - case HB_MODE_ERROR: - { - if( modeChanged ) - { - 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 ); - fSuspendButton->SetLabel( "Suspend" ); - fSuspendButton->SetEnabled( false ); - fStartButton->SetLabel( "Rip !" ); - fStartButton->SetEnabled( true ); - } - - fStatusBar->Update( - fStatusBar->CurrentValue(), - "Error." ); - break; - } - - default: - break; - } -} - diff --git a/beos/RipView.h b/beos/RipView.h deleted file mode 100644 index 1036e9261..000000000 --- a/beos/RipView.h +++ /dev/null @@ -1,77 +0,0 @@ -/* $Id: RipView.h,v 1.4 2003/11/09 21:35:06 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - 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 "HandBrake.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( HBHandle * handle ); - void MessageReceived( BMessage * message ); - void UpdateIntf( HBStatus status, int modeChanged ); - - private: - HBHandle * fHandle; - 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 deleted file mode 100644 index 24c66db7f..000000000 --- a/beos/ScanView.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* $Id: ScanView.cpp,v 1.2 2003/11/06 14:36:54 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - 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 "ScanView.h" - -ScanView::ScanView( HBHandle * handle ) - : BView( BRect( 0,0,400,190 ), NULL, B_FOLLOW_ALL, B_WILL_DRAW ) -{ - fHandle = handle; - - 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() ) - { - HBScanDevice( fHandle, - (char*) fPopUp->FindMarked()->Label(), - 0 ); - } - else - { - HBScanDevice( fHandle, - (char*) fFolderControl->Text(), 0 ); - } - break; - } - - default: - BView::MessageReceived( message ); - } -} - -void ScanView::UpdateIntf( HBStatus status, int modeChanged ) -{ - switch( status.mode ) - { - case HB_MODE_SCANNING: - { - if( modeChanged ) - { - 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.scannedTitle ) - { - sprintf( string, "Opening device..." ); - } - else - { - sprintf( string, "Scanning title %d...", - status.scannedTitle ); - } - fStatusString->SetText( string ); - break; - } - - case HB_MODE_INVALID_DEVICE: - { - if( !modeChanged ) - break; - - 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 deleted file mode 100644 index 11ed342cc..000000000 --- a/beos/ScanView.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $Id: ScanView.h,v 1.2 2003/11/06 14:36:54 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - 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 "HandBrake.h" - -#define SCAN_RADIO 'scra' -#define SCAN_BROWSE_BUTTON 'sbrb' -#define SCAN_OPEN 'scop' - -class ScanView : public BView -{ - public: - ScanView( HBHandle * handle ); - void MessageReceived( BMessage * message ); - void UpdateIntf( HBStatus status, int modeChanged ); - - private: - void DetectVolumes(); - - HBHandle * fHandle; - - BRadioButton * fRadioDetected; - BRadioButton * fRadioFolder; - BMenuField * fField; - BPopUpMenu * fPopUp; - BTextControl * fFolderControl; - BButton * fBrowseButton; - BFilePanel * fFilePanel; - BStringView * fStatusString; - BButton * fOpenButton; -}; - -#endif diff --git a/beos/liblayout/HGroup.h b/beos/liblayout/HGroup.h new file mode 100644 index 000000000..9eee83fea --- /dev/null +++ b/beos/liblayout/HGroup.h @@ -0,0 +1,40 @@ + +#ifndef _HGROUP_H +#define _HGROUP_H +#include "MGroup.h" +#include <View.h> +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT HGroup : public MGroup, public BView +{ + public: HGroup(minimax mpm,MView *kid=0, ...); + HGroup(MView *kid=0, ...); + HGroup(BMessage*); + virtual ~HGroup(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void MouseDown(BPoint); + + private: virtual void _expansionhgroup1(); + virtual void _expansionhgroup2(); + virtual void _expansionhgroup3(); + + static int cmpkids(const void* v1,const void *v2); + int *size; + float totalweight; + int numkids; + sortstruct *childorder; + MView **mkid; + float totalminx,totalmaxx; + BRect *lastrect; + + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/LayeredGroup.h b/beos/liblayout/LayeredGroup.h new file mode 100644 index 000000000..61264ca36 --- /dev/null +++ b/beos/liblayout/LayeredGroup.h @@ -0,0 +1,37 @@ + +#ifndef _LAYEREDGROUP_H +#define _LAYEREDGROUP_H + +#include "MGroup.h" +#include <Control.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT LayeredGroup : public MGroup, public BControl +{ + public: LayeredGroup(minimax mpm,MView *arg=0, ...); + LayeredGroup(MView *arg=0, ...); + LayeredGroup(BMessage*); + virtual ~LayeredGroup(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + void ActivateLayer(int); + virtual void MessageReceived(BMessage *mes); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: virtual void _expansionlayeredgroup1(); + virtual void _expansionlayeredgroup2(); + + int numkids; + int activekid; + + uint32 _expansiondata[3]; +}; + + +#endif diff --git a/beos/liblayout/MApplication.h b/beos/liblayout/MApplication.h new file mode 100644 index 000000000..acdd13214 --- /dev/null +++ b/beos/liblayout/MApplication.h @@ -0,0 +1,29 @@ + +#ifndef _MAPPLICATION_H +#define _MAPPLICATION_H + +#include "layout.h" +#include <Application.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MApplication : public BApplication +{ + public: MApplication(char *); + MApplication(BMessage*); + virtual ~MApplication(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual void MessageReceived(BMessage*); + + virtual status_t GetSupportedSuites(BMessage *message); + virtual BHandler *ResolveSpecifier(BMessage *message, int32 index, BMessage *specifier, int32 command, const char *property); + + private: + virtual void _expansionmapplication1(); + virtual void _expansionmapplication2(); + uint32 _expansiondata[4]; +}; +#endif diff --git a/beos/liblayout/MBViewWrapper.h b/beos/liblayout/MBViewWrapper.h new file mode 100644 index 000000000..351dfb800 --- /dev/null +++ b/beos/liblayout/MBViewWrapper.h @@ -0,0 +1,30 @@ + +#ifndef _MBVIEWWRAPPER_H +#define _MBVIEWWRAPPER_H +#include "layout.h" +#include <View.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MBViewWrapper : public MView, public BView +{ + public: MBViewWrapper(BView *view, bool usepreferred=true, bool x_fixed=true, bool y_fixed=true); + MBViewWrapper(BMessage*); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual ~MBViewWrapper(); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: virtual void _expansionmbviewwrapper1(); + + BView *childview; + + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/MBorder.h b/beos/liblayout/MBorder.h new file mode 100644 index 000000000..4e925ec2d --- /dev/null +++ b/beos/liblayout/MBorder.h @@ -0,0 +1,68 @@ + +#ifndef _MBORDER_H +#define _MBORDER_H +#include "MGroup.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MBorder : public MGroup, public BView +{ + public: + enum { + ROTATE_REVERSE=(int)0x80000000 + }; + + MBorder(ulong border_type,ulong spacing,char *name=NULL,MView *kid=NULL); + MBorder(BMessage*); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + ~MBorder(); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void Draw(BRect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void FrameResized(float width, float height); + void DrawBorder(); + void SetLabel(char *); + char *Label(); + void SetHighlight(int); + void SetHighlightColors(rgb_color color1, rgb_color color2, rgb_color color3); + + private: + virtual void _expansionmborder1(); + virtual void _expansionmborder2(); + + static long _cycler(void *arg); + void Cycler(); + int highlightmode; + thread_id cycler; + + ulong bordertype; + ulong extraspacing; + ulong extralabelspacing; + char *label; + char *truncatedlabel; + + rgb_color *highlightcolors; + + uint32 _expansiondata[1]; +}; + + +enum +{ + M_NO_BORDER, + M_RAISED_BORDER, + M_DEPRESSED_BORDER, + M_LABELED_BORDER, + M_ETCHED_BORDER +}; + +enum +{ + M_SHOW_FULL_LABEL= 0x00000100 +}; +#endif diff --git a/beos/liblayout/MButton.h b/beos/liblayout/MButton.h new file mode 100644 index 000000000..64cd3e32b --- /dev/null +++ b/beos/liblayout/MButton.h @@ -0,0 +1,53 @@ + +#ifndef _MBUTTON +#define _MBUTTON +#include "layout.h" +#include <Button.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MButton : public MView, public BButton +{ + public: ulong ID; + + MButton(const char *label, ulong id=0,minimax size=minimax(-1,-1,1E6,1E6,1)); + MButton(const char *label, BMessage *message, BHandler *handler=NULL, minimax size=minimax(-1,-1,1E6,1E6,1)); + MButton(BMessage*); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual ~MButton(); + void SetRepeat(ulong initial_delay, ulong repeat_delay); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void setcolor(rgb_color, bool); + + virtual void Draw(BRect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + virtual void MouseDown(BPoint); + + private: static long _mousetracker(void *arg); + void _MouseTracker(); + thread_id mousethread; + BHandler *target; + int64 lastwhen; + ulong initialdelay; + ulong repeatdelay; + void initobject(); + ulong buttonmask; + + uint32 _expansiondata[2]; +}; + +extern const IMPEXPLIBLAYOUT char M_BUTTON_POINTER[]; +extern const IMPEXPLIBLAYOUT char M_BUTTON_ID[]; +extern const IMPEXPLIBLAYOUT char M_BUTTON_MASK[]; +extern const IMPEXPLIBLAYOUT char M_DOUBLECLICK[]; +extern const IMPEXPLIBLAYOUT char M_REPEAT[]; +extern const IMPEXPLIBLAYOUT char M_RELEASE[]; + +#endif diff --git a/beos/liblayout/MCheckBox.h b/beos/liblayout/MCheckBox.h new file mode 100644 index 000000000..7b39abda2 --- /dev/null +++ b/beos/liblayout/MCheckBox.h @@ -0,0 +1,33 @@ + +#ifndef _MCHECKBOX +#define _MCHECKBOX +#include "layout.h" +#include <CheckBox.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MCheckBox : public MView, public BCheckBox +{ + public: MCheckBox(const char *label,ulong id=0, bool state=false); + MCheckBox(const char *label, BMessage *message, BHandler *handler=NULL, bool state=false); + MCheckBox(BMessage*); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual ~MCheckBox(); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + + private: BHandler *target; + uint32 _expansiondata[2]; +}; + +extern const IMPEXPLIBLAYOUT char M_CHECKBOX_POINTER[]; +extern const IMPEXPLIBLAYOUT char M_CHECKBOX_ID[]; + +#endif diff --git a/beos/liblayout/MDividable.h b/beos/liblayout/MDividable.h new file mode 100644 index 000000000..800772b88 --- /dev/null +++ b/beos/liblayout/MDividable.h @@ -0,0 +1,35 @@ + +// Abstract base class for an object that can be 'divided'. +// Currently this includes MTextControl and MPopup. +// The dividable class, and the global function below, is +// used to align the left half (the label) and the right +// half (data-entry/selection) of a group of MDividable's + +#ifndef _MDIVIDABLE_H +#define _MDIVIDABLE_H + +#include "layout.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MDividable +{ + public: + float labelwidth; + MDividable *rolemodel; + + public: + MDividable(); +// work around my own bug... +#ifdef BUILDING_LIBLAYOUT + ~MDividable(); +#endif + void DivideSameAs(MDividable *); + virtual float LabelWidth(); +}; + +extern void IMPEXPLIBLAYOUT DivideSame(MView *, MView *, ...); + +#endif diff --git a/beos/liblayout/MDragBar.h b/beos/liblayout/MDragBar.h new file mode 100644 index 000000000..e345668c4 --- /dev/null +++ b/beos/liblayout/MDragBar.h @@ -0,0 +1,38 @@ + +#ifndef _MDRAGBAR_H +#define _MDRAGBAR_H +#include "layout.h" +#include <Control.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MDragBar : public MView, public BControl +{ + public: MDragBar(minimax size=minimax(1,1,1E6,1E6)); + MDragBar(BMessage*); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual ~MDragBar(); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void AttachedToWindow(); + virtual void Draw(BRect rect); + virtual void KeyDown(const char *bytes, int32 numbytes); + virtual void DetachedFromWindow(); + virtual void MouseDown(BPoint); + + private: virtual void _expansionmdragbar1(); + + thread_id mousethread; + BPoint dragpoint; + + static long _mousetracker(void *arg); + void _MouseTracker(); + + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/MEject.h b/beos/liblayout/MEject.h new file mode 100644 index 000000000..a9c017346 --- /dev/null +++ b/beos/liblayout/MEject.h @@ -0,0 +1,23 @@ +#ifndef _MEJECT_H +#define _MEJECT_H + +#include "MPictureButton.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MEject : public MPictureButton +{ + public: MEject(BHandler *id); + MEject(BHandler *id, BMessage*); + MEject(BMessage*); + virtual ~MEject(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual void MakePictures(); +}; +extern const IMPEXPLIBLAYOUT char M_BUTTON_POINTER[]; + +#endif diff --git a/beos/liblayout/MFFWD.h b/beos/liblayout/MFFWD.h new file mode 100644 index 000000000..97c0d53e1 --- /dev/null +++ b/beos/liblayout/MFFWD.h @@ -0,0 +1,24 @@ +#ifndef _MFFWD_H +#define _MFFWD_H + +#include "MPictureButton.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MFFWD : public MPictureButton +{ + public: MFFWD(BHandler *id=NULL); + MFFWD(BHandler *id, BMessage*); + MFFWD(BMessage*); + virtual ~MFFWD(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual void MakePictures(); +}; + +extern const IMPEXPLIBLAYOUT char M_BUTTON_POINTER[]; + +#endif diff --git a/beos/liblayout/MGroup.h b/beos/liblayout/MGroup.h new file mode 100644 index 000000000..73dcbfb9c --- /dev/null +++ b/beos/liblayout/MGroup.h @@ -0,0 +1,31 @@ +/* + + MGroup is an abstract class from which all groups should derive. + +*/ + +#ifndef _MGROUP_H +#define _MGROUP_H + +#include "layout.h" +#include <View.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MGroup : public MView +{ + public: MGroup(); + virtual ~MGroup(); + + virtual void reloadfont(BFont *font[]); +}; + +typedef struct +{ + MView *kid; + int kidnum; +} sortstruct; + +#endif diff --git a/beos/liblayout/MListView.h b/beos/liblayout/MListView.h new file mode 100644 index 000000000..95c4d42ca --- /dev/null +++ b/beos/liblayout/MListView.h @@ -0,0 +1,30 @@ + +#ifndef _MLISTVIEW_H +#define _MLISTVIEW_H +#include "layout.h" +#include <ListView.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MListView : public MView, public BListView +{ + public: MListView(list_view_type type=B_SINGLE_SELECTION_LIST, + minimax size=minimax(50,50)); + MListView(BMessage*); + virtual ~MListView(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual void reloadfont(BFont *font[]); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void MessageReceived(BMessage*); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: virtual void _expansionmlistview1(); + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/MMenuBar.h b/beos/liblayout/MMenuBar.h new file mode 100644 index 000000000..a5b061a19 --- /dev/null +++ b/beos/liblayout/MMenuBar.h @@ -0,0 +1,33 @@ + +#ifndef _MMENUBAR_H +#define _MMENUBAR_H + +#include "layout.h" +#include <MenuBar.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MMenuBar: public MView, public BMenuBar +{ + public: + MMenuBar(menu_layout layout=B_ITEMS_IN_ROW); + MMenuBar(menu_layout layout, bool resizetofit); + MMenuBar(BMessage*); + virtual ~MMenuBar(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect); + virtual void reloadfont(BFont *font[]); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + private: + virtual void _expansionmmenubar1(); + virtual void _expansionmmenubar2(); + + uint32 _expansiondata[2]; +}; +#endif diff --git a/beos/liblayout/MOutlineListView.h b/beos/liblayout/MOutlineListView.h new file mode 100644 index 000000000..acb00e19b --- /dev/null +++ b/beos/liblayout/MOutlineListView.h @@ -0,0 +1,32 @@ + +#ifndef _MOUTLINELISTVIEW_H +#define _MOUTLINELISTVIEW_H +#include "layout.h" +#include <OutlineListView.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MOutlineListView : public MView, public BOutlineListView +{ + public: MOutlineListView(list_view_type type=B_SINGLE_SELECTION_LIST, + minimax size=minimax(50,50)); + MOutlineListView(BMessage*); + virtual ~MOutlineListView(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual void reloadfont(BFont *font[]); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void MessageReceived(BMessage*); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: virtual void _expansionmoutlinelistview1(); + virtual void _expansionmoutlinelistview2(); + + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/MPictureButton.h b/beos/liblayout/MPictureButton.h new file mode 100644 index 000000000..687b5c28a --- /dev/null +++ b/beos/liblayout/MPictureButton.h @@ -0,0 +1,55 @@ +#ifndef _MPICTUREBUTTON_H +#define _MPICTUREBUTTON_H + +#include "layout.h" +#include <PictureButton.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MPictureButton : public MView, public BPictureButton +{ + public: + MPictureButton(minimax size, BPicture *off, BPicture *on, + BMessage *message=NULL, BHandler *target=NULL, + uint32 behavior=B_ONE_STATE_BUTTON); + MPictureButton(BMessage *archive); + virtual ~MPictureButton(); + void SetRepeat(ulong initial_delay, ulong repeat_delay); + + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect); + virtual void setcolor(rgb_color col, bool deep=false); + virtual void MakePictures(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void MouseDown(BPoint); + + private: + virtual void _expansionmpicturebutton1(); + virtual void _expansionmpicturebutton2(); + + thread_id mousethread; + int64 lastwhen; + ulong initialdelay; + ulong repeatdelay; + ulong buttonmask; + BHandler *target; + + static long _mousetracker(void *arg); + void _MouseTracker(); + + uint32 _expansiondata[2]; +}; + +extern const IMPEXPLIBLAYOUT char M_DOUBLECLICK[]; +extern const IMPEXPLIBLAYOUT char M_BUTTON_MASK[]; +extern const IMPEXPLIBLAYOUT char M_REPEAT[]; +extern const IMPEXPLIBLAYOUT char M_RELEASE[]; + +#endif diff --git a/beos/liblayout/MPlayBW.h b/beos/liblayout/MPlayBW.h new file mode 100644 index 000000000..043aa46d3 --- /dev/null +++ b/beos/liblayout/MPlayBW.h @@ -0,0 +1,23 @@ +#ifndef _MPLAYBW_H +#define _MPLAYBW_H + +#include "MPictureButton.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MPlayBW : public MPictureButton +{ + public: MPlayBW(BHandler*); + MPlayBW(BHandler *id, BMessage*); + MPlayBW(BMessage*); + virtual ~MPlayBW(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual void MakePictures(); +}; +extern const IMPEXPLIBLAYOUT char M_BUTTON_POINTER[]; + +#endif diff --git a/beos/liblayout/MPlayFW.h b/beos/liblayout/MPlayFW.h new file mode 100644 index 000000000..7f847df7b --- /dev/null +++ b/beos/liblayout/MPlayFW.h @@ -0,0 +1,22 @@ +#ifndef _MPLAYFW_H +#define _MPLAYFW_H + +#include "MPictureButton.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MPlayFW : public MPictureButton +{ + public: MPlayFW(BHandler*); + MPlayFW(BHandler *id, BMessage*); + MPlayFW(BMessage*); + virtual ~MPlayFW(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual void MakePictures(); +}; +extern const IMPEXPLIBLAYOUT char M_BUTTON_POINTER[]; + +#endif diff --git a/beos/liblayout/MPopup.h b/beos/liblayout/MPopup.h new file mode 100644 index 000000000..2223664ec --- /dev/null +++ b/beos/liblayout/MPopup.h @@ -0,0 +1,45 @@ + +#ifndef _MPOPUP_H +#define _MPOPUP_H +#include "layout.h" +#include "MDividable.h" +#include <MenuField.h> + +class BPopUpMenu; + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MPopup: + public MView, public MDividable, public BMenuField +{ + public: MPopup(char *label, char *item ...); + MPopup(char *label, BMessage*, BHandler *, char *item ...); + MPopup(BMessage*); + virtual ~MPopup(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual float LabelWidth(); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void reloadfont(BFont *font[]); + void SetActive(ulong, bool send=true); + void EnableItem(ulong index, bool enabled); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: virtual void _expansionmpopup1(); + + char *poplabel; + BHandler *target; + BPopUpMenu *popup; + + uint32 _expansiondata[2]; +}; + +extern const IMPEXPLIBLAYOUT char M_POPUP_POINTER_NAME[]; + +#endif diff --git a/beos/liblayout/MProgressBar.h b/beos/liblayout/MProgressBar.h new file mode 100644 index 000000000..3938c2583 --- /dev/null +++ b/beos/liblayout/MProgressBar.h @@ -0,0 +1,58 @@ + +#ifndef _MSTATUSBAR_H +#define _MSTATUSBAR_H +#include "layout.h" +#include <View.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MProgressBar : public MView, public BView +{ + public: float value; + float currentwidth; + + public: MProgressBar(BHandler *, bool pulsed_updates=false); + MProgressBar(BMessage*); + virtual ~MProgressBar(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void setcolor(rgb_color,bool); + void setbarcolor(rgb_color); + rgb_color getbarcolor() {return bar_fill;}; + virtual void Draw(BRect); + virtual void Pulse(); + void Refresh(); + void SetValue(float value); + virtual void MouseDown(BPoint); + virtual void WindowActivated(bool); + virtual void FrameResized(float,float); + virtual void MessageReceived(BMessage *mes); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: virtual void _expansionmprogressbar1(); + virtual void _expansionmprogressbar2(); + + thread_id mousethread; + static long _mousetracker(void *arg); + long mousetracker(); + + BRect lastbounds; + BHandler *target; + rgb_color bar_hi; + rgb_color bar_fill; + rgb_color bar_low; + float barwidth; + + uint32 _expansiondata[2]; +}; + +extern const IMPEXPLIBLAYOUT char M_PROGRESSBAR_FRACTION[]; + +#endif + diff --git a/beos/liblayout/MRadioGroup.h b/beos/liblayout/MRadioGroup.h new file mode 100644 index 000000000..bb430f2da --- /dev/null +++ b/beos/liblayout/MRadioGroup.h @@ -0,0 +1,46 @@ + +#ifndef _MRADIOGROUP_H +#define _MRADIOGROUP_H +#include "MGroup.h" +#include <RadioButton.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MRadioGroup : public MGroup, public BView +{ + public: MRadioGroup(char *item ...); + MRadioGroup(BMessage *model, char *item ...); + MRadioGroup(BMessage *model, BHandler *target, char *item ...); + MRadioGroup(BMessage*); + virtual ~MRadioGroup(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void SetActive(ulong); + virtual long ActiveButton(); + virtual void reloadfont(BFont *font[]); + virtual void setcolor(rgb_color col,bool deep); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: virtual void _expansionmradiogroup1(); + virtual void _expansionmradiogroup2(); + + ulong numradios; + BHandler *handler; + + uint32 _expansiondata[3]; +}; + +extern const IMPEXPLIBLAYOUT char M_RADIO_POINTER_NAME[]; +extern const IMPEXPLIBLAYOUT char M_RADIO_INDEX_NAME[]; + + +#endif + + + diff --git a/beos/liblayout/MRew.h b/beos/liblayout/MRew.h new file mode 100644 index 000000000..f21683b5d --- /dev/null +++ b/beos/liblayout/MRew.h @@ -0,0 +1,22 @@ +#ifndef _MREW_H +#define _MREW_H + +#include "MPictureButton.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MRew : public MPictureButton +{ + public: MRew(BHandler*); + MRew(BHandler *id, BMessage*); + MRew(BMessage*); + virtual ~MRew(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual void MakePictures(); +}; +extern const IMPEXPLIBLAYOUT char M_BUTTON_POINTER[]; + +#endif diff --git a/beos/liblayout/MScrollView.h b/beos/liblayout/MScrollView.h new file mode 100644 index 000000000..8ba21ce0e --- /dev/null +++ b/beos/liblayout/MScrollView.h @@ -0,0 +1,39 @@ + +#ifndef _MSCROLLVIEW_H +#define _MSCROLLVIEW_H + +#include "layout.h" +#include <ScrollView.h> + +// An MScrollView accepts another MView as its target. +// The MScrollView will display scrollbars as requested +// so that the target MView may be scrolled left/right or +// up/down. + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MScrollView: public MView, public BScrollView +{ + public: + MScrollView(MView *target, bool horizontal=false, bool vertical=false, + border_style border=B_FANCY_BORDER, minimax size=0); + MScrollView(BMessage*); + virtual ~MScrollView(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual minimax layoutprefs(); + virtual BRect layout(BRect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: + MView *kid; + float leftinset; + float rightinset; + float topinset; + float bottominset; +}; + +#endif diff --git a/beos/liblayout/MSlider.h b/beos/liblayout/MSlider.h new file mode 100644 index 000000000..6e7077d3d --- /dev/null +++ b/beos/liblayout/MSlider.h @@ -0,0 +1,30 @@ + + +#ifndef _MSLIDER_H +#define _MSLIDER_H + +#include "layout.h" +#include "Slider.h" + +class IMPEXPLIBLAYOUT MSlider: public MView, public BSlider +{ + public: + MSlider(const char *label, int32 minval, int32 maxval,int32 granularity=1, BMessage *message=NULL, BHandler *target=NULL, thumb_style ts=B_BLOCK_THUMB); + virtual ~MSlider(); + virtual void AllAttached(); + virtual void DetachedFromWindow(); + virtual void SetValue(int32 value); + void SetGranularity(int32 granul); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect); + + private: + virtual void _expansionmslider1(); + virtual void _expansionmslider2(); + BHandler *target; + int32 granularity; + uint32 _expansiondata[4]; +}; + +#endif diff --git a/beos/liblayout/MSplitter.h b/beos/liblayout/MSplitter.h new file mode 100644 index 000000000..411c5d14f --- /dev/null +++ b/beos/liblayout/MSplitter.h @@ -0,0 +1,38 @@ + +#ifndef _MSPLITTER_H +#define _MSPLITTER_H + +#include "layout.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MSplitter : public MView, public BView +{ + public: MSplitter(); + MSplitter(bool cosmetic); + MSplitter(BMessage*); + virtual ~MSplitter(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void MouseDown(BPoint); + virtual void Draw(BRect); + virtual void MouseMoved(BPoint, ulong, const BMessage*); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: + float siblingweight; + MView *previoussibling; + MView *nextsibling; + thread_id mousethread; + static long _mousetracker(void *); + void _MouseTracker(void); + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/MStop.h b/beos/liblayout/MStop.h new file mode 100644 index 000000000..b99fc2fe4 --- /dev/null +++ b/beos/liblayout/MStop.h @@ -0,0 +1,22 @@ +#ifndef _MSTOP_H +#define _MSTOP_H + +#include "MPictureButton.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MStop : public MPictureButton +{ + public: MStop(BHandler*); + MStop(BHandler *id, BMessage*); + MStop(BMessage*); + virtual ~MStop(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual void MakePictures(); +}; +extern const IMPEXPLIBLAYOUT char M_BUTTON_POINTER[]; + +#endif diff --git a/beos/liblayout/MStringView.h b/beos/liblayout/MStringView.h new file mode 100644 index 000000000..4db74452e --- /dev/null +++ b/beos/liblayout/MStringView.h @@ -0,0 +1,25 @@ + +#ifndef _MSTRINGVIEW_H +#define _MSTRINGVIEW_H +#include "layout.h" +#include <StringView.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MStringView : public MView, public BStringView +{ + public: MStringView(const char *label,alignment a=B_ALIGN_LEFT,minimax size=minimax(10,10,65536,65536,1)); + MStringView(BMessage*); + virtual ~MStringView(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); +}; + +#endif diff --git a/beos/liblayout/MTabView.h b/beos/liblayout/MTabView.h new file mode 100644 index 000000000..04c69ec59 --- /dev/null +++ b/beos/liblayout/MTabView.h @@ -0,0 +1,33 @@ + +#ifndef _MTABVIEW_H +#define _MTABVIEW_H + +#include <TabView.h> +#include "MGroup.h" + +class IMPEXPLIBLAYOUT MTab: public BTab +{ + public: + MTab(MView *view, const char *name=NULL); + MTab(BMessage *archive); + virtual ~MTab(); +}; + + +class IMPEXPLIBLAYOUT MTabView: public MGroup, public BTabView +{ + public: + MTabView(); + MTabView(BMessage *archive); + virtual void Add(MTab *tab); + virtual void Select(int32 tab); + + virtual void reloadfont(BFont *font[]); + virtual minimax layoutprefs(); + virtual BRect layout(BRect); + + private: + void LayoutCurrentTab(); +}; + +#endif diff --git a/beos/liblayout/MTextControl.h b/beos/liblayout/MTextControl.h new file mode 100644 index 000000000..46f1a746f --- /dev/null +++ b/beos/liblayout/MTextControl.h @@ -0,0 +1,36 @@ + +#ifndef _MTEXTCONTROL_H +#define _MTEXTCONTROL_H +#include "layout.h" +#include "MDividable.h" +#include <TextControl.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MTextControl: + public MView, public MDividable, public BTextControl +{ + public: MTextControl(char *label, char *text); + MTextControl(char *label, char *text, BMessage *mes); + MTextControl(BMessage*); + virtual ~MTextControl(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual void SetLabel(const char *); + virtual float LabelWidth(); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void reloadfont(BFont *font[]); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + private: float lastheight; + + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/MTextView.h b/beos/liblayout/MTextView.h new file mode 100644 index 000000000..512a85cd1 --- /dev/null +++ b/beos/liblayout/MTextView.h @@ -0,0 +1,31 @@ + +#ifndef _MTEXTVIEW_H +#define _MTEXTVIEW_H +#include "layout.h" +#include <TextView.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MTextView : public MView, public BTextView +{ + public: MTextView(minimax size=0); + MTextView(BMessage*); + virtual ~MTextView(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void MessageReceived(BMessage *mes); + + private: void initobject(); + static long AsyncSetTextRect(void *arg); + thread_id resizer; + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/MVolume.h b/beos/liblayout/MVolume.h new file mode 100644 index 000000000..9d70b7955 --- /dev/null +++ b/beos/liblayout/MVolume.h @@ -0,0 +1,48 @@ +#ifndef _MVOLUME_H +#define _MVOLUME_H + +#include "layout.h" +#include <Control.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MVolume : public MView, public BControl +{ + public: MVolume(BHandler*); + MVolume(BMessage*); + virtual ~MVolume(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual minimax layoutprefs(); + BRect layout(BRect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void Draw(BRect); + virtual void DrawVolume(void); + float Volume(); + void SetVolume(float vol); + virtual void MouseDown(BPoint); + virtual void KeyDown(const char *bytes, int32 numbytes); + + private: float volume; + BHandler *target; + BPoint lastvoldot; + BPoint clickpoint; + thread_id mousethread; + bool ispressed; + // moved into private area 21-6-98 + static long _mousetracker(void *arg); + void _MouseTracker(); + // added 21-6-98 + void _PUMouseTracker(); +}; + +inline float MVolume::Volume() +{ + return volume; +} + +#endif diff --git a/beos/liblayout/MWindow.h b/beos/liblayout/MWindow.h new file mode 100644 index 000000000..6118f87bc --- /dev/null +++ b/beos/liblayout/MWindow.h @@ -0,0 +1,62 @@ + +#ifndef _MWINDOW_H +#define _MWINDOW_H + +#include "layout.h" +#include <Window.h> + +class BPopUpMenu; + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT MWindow : public BWindow +{ + public: + ulong flags; + + MWindow(BRect r,const char *name,window_type type,uint32 flags, uint32 workspaces=B_CURRENT_WORKSPACE); + MWindow(BRect r,const char *name,window_look look, window_feel feel,uint32 flags, uint32 workspaces=B_CURRENT_WORKSPACE); + MWindow(BMessage*); + virtual ~MWindow(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + virtual const BFont *getfont(fontspec font); + + virtual void MessageReceived(BMessage *message); + virtual void Show(); + virtual void RecalcSize(); + virtual void FrameResized(float width, float height); + + virtual status_t GetSupportedSuites(BMessage *message); + virtual BHandler *ResolveSpecifier(BMessage *message, int32 index, BMessage *specifier, int32 command, const char *property); + virtual void ScreenChanged(BRect frame, color_space mode); + virtual void WorkspaceActivated(int32 workspace, bool active); + + void StartDragging(); + static long _mousetracker(void *arg); + void _MouseTracker(); + + private: + virtual void _expansionmwindow1(); + virtual void _expansionmwindow2(); + virtual void _expansionmwindow3(); + + void initobject(); + BFont **fontlist; + BRect lastrect; + BPopUpMenu *pop; + thread_id mousethread; + BPoint dragpoint; + + uint32 _expansiondata[1]; +}; + +enum { + M_WIN_AUTORESIZE =0x00000100, + M_WIN_ESCAPETOCLOSE=0x00000200 +}; + +#endif // MWINDOW_H diff --git a/beos/liblayout/PropGadget.h b/beos/liblayout/PropGadget.h new file mode 100644 index 000000000..81a3f1f9b --- /dev/null +++ b/beos/liblayout/PropGadget.h @@ -0,0 +1,75 @@ + +#ifndef _PROPGADGET +#define _PROPGADGET +#include "layout.h" +#include <Control.h> +#include <Bitmap.h> + +class IMPEXPLIBLAYOUT PropGadget; + +typedef void (*propgadget_hook)(PropGadget*, void*, double, double); + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class PropGadget : public MView, public BControl +{ + public: PropGadget(double xprop, double xval, double yprop, double yval, + BBitmap *knobimage=NULL, + propgadget_hook=NULL, + void *callbackarg=NULL, + long extraspacing=0); + PropGadget(BMessage*); + virtual ~PropGadget(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + + BBitmap* Pknob; + + virtual void Draw(BRect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void MouseDown(BPoint); + + void SetProportion(double, double); + void SetProportionNoDraw(double,double); + virtual void SetValues(double,double); + void SetValuesNoDraw(double,double); + virtual void FrameResized(float,float); + void ReDraw(); + inline double Hval() {return hval;} + inline double Vval() {return 1.0-vval;} + + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void setcolor(rgb_color col, bool deep=false); + virtual void DrawContainer(BRect); + virtual void DrawKnob(BRect); + virtual void KeyDown(const char *bytes, int32 numbytes); + bool IsBusy(); + + private: virtual void _expansionpropgadget1(); + virtual void _expansionpropgadget2(); + + thread_id mousethread; + BPoint clickpoint; + BRect lastknobrect; + bool _isbusy; + bool vertical; + bool horizontal; + + double hprop; + double hval; + double vprop; + double vval; + void (*callback)(PropGadget*,void*,double,double); + void *callbackarg; + long borderspacing; + + static long _mousetracker(void *arg); + void _MouseTracker(); + + uint32 _expansiondata[2]; +}; +#endif diff --git a/beos/liblayout/Space.h b/beos/liblayout/Space.h new file mode 100644 index 000000000..c49f6fbd2 --- /dev/null +++ b/beos/liblayout/Space.h @@ -0,0 +1,22 @@ + +#ifndef _SPACE_H +#define _SPACE_H +#include "layout.h" +#include "View.h" + +#if __POWERPC__ +#pragma simple_class_byval off +#endif +class IMPEXPLIBLAYOUT Space : public MView, public BView +{ + public: Space(); + Space(minimax); + Space(BMessage*); + virtual ~Space(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); +}; + +#endif diff --git a/beos/liblayout/SpinButton.h b/beos/liblayout/SpinButton.h new file mode 100644 index 000000000..3bb00db69 --- /dev/null +++ b/beos/liblayout/SpinButton.h @@ -0,0 +1,78 @@ + +#ifndef _SPINBUTTON_H +#define _SPINBUTTON_H + +#include <View.h> +#include "layout.h" +#include "HGroup.h" +#include "MTextControl.h" + +enum spinmode +{ + SPIN_FLOAT, + SPIN_INTEGER +}; + +class NumberTextView; +class TinyButton; +#if __POWERPC__ +#pragma warn_hidevirtual off +#endif +class IMPEXPLIBLAYOUT SpinButton: public MView, public MDividable, public BControl +{ + public: + SpinButton(const char *label,spinmode mode, BHandler *target=NULL); + virtual ~SpinButton(); + + virtual void reloadfont(BFont *font[]); + virtual minimax layoutprefs(); + virtual BRect layout(BRect); + + virtual float LabelWidth(); + + virtual void AllAttached(); + virtual void DetachedFromWindow(); + virtual void Draw(BRect); + virtual void MessageReceived(BMessage *mes); + virtual void SetEnabled(bool); + + double Increment(); + double Decrement(); + double StepSize(); + void SetStepSize(double step); + + virtual void SetValue(int32 v); + virtual void SetValue(double v); + double Value(); + double Maximum(); + void SetMaximum(double max); + double Minimum(); + void SetMinimum(double min); + const char * Format() const; + void SetFormat(const char *f); + + private: + spinmode mode; + ulong height; + TinyButton *tb1,*tb2; + NumberTextView *tv; + long lx,ly; + void NotifyWorld(BMessage *mes); + BHandler *target; + uint32 _expansiondata[4]; +}; + +enum +{ + M_SPIN_UP='!!up', + M_SPIN_DOWN='!!dn', + M_SPIN_TICK='!spn' +}; + +extern const IMPEXPLIBLAYOUT char M_RELEASE[]; + +#if __POWERPC__ +#pragma warn_hidevirtual on +#endif + +#endif diff --git a/beos/liblayout/TabGroup.h b/beos/liblayout/TabGroup.h new file mode 100644 index 000000000..64a2cf9cc --- /dev/null +++ b/beos/liblayout/TabGroup.h @@ -0,0 +1,46 @@ + +#ifndef _TABGROUP_H +#define _TABGROUP_H + +#include "MGroup.h" +#include <Control.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT TabGroup : public MGroup, public BControl +{ + public: TabGroup(minimax mpm,char *arg=0, ...); + TabGroup(char *arg=0, ...); + TabGroup(BMessage*); + virtual ~TabGroup(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void AttachedToWindow(); + virtual void MouseDown(BPoint point); + virtual void Draw(BRect clip); + virtual void KeyDown(const char *bytes, int32 numbytes); + virtual void ActivateTab(int); + int32 ActiveTab(); + virtual void DetachedFromWindow(); + virtual void SetEnabled(bool enabled); + void SetExtraSpacing(float spacing); + float ExtraSpacing(); + + private: virtual void _expansiontabgroup1(); + virtual void _expansiontabgroup2(); + + int numkids; + int activekid; + float tabheight; + float biggesttabmin; + float fontdescent; + float extraspacing; + + uint32 _expansiondata[1]; +}; + +#endif diff --git a/beos/liblayout/VGroup.h b/beos/liblayout/VGroup.h new file mode 100644 index 000000000..56be070df --- /dev/null +++ b/beos/liblayout/VGroup.h @@ -0,0 +1,41 @@ + +#ifndef _VGROUP_H +#define _VGROUP_H +#include "MGroup.h" +#include <View.h> + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +class IMPEXPLIBLAYOUT VGroup : public MGroup, public BView +{ + public: VGroup(minimax mpm,MView *kid=0, ...); + VGroup(MView *kid=0, ...); + VGroup(BMessage*); + virtual ~VGroup(); + virtual long Archive(BMessage *archive, bool deep=true) const; + static BArchivable *Instantiate(BMessage *archive); + virtual minimax layoutprefs(); + virtual BRect layout(BRect rect); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void MouseDown(BPoint); + + private: virtual void _expansionvgroup1(); + virtual void _expansionvgroup2(); + virtual void _expansionvgroup3(); + + static int cmpkids(const void* v1,const void *v2); + int *size; + float totalweight; + int numkids; + sortstruct *childorder; + MView **mkid; + float totalminy,totalmaxy; + BRect *lastrect; + + uint32 _expansiondata[2]; +}; + +#endif diff --git a/beos/liblayout/layout-all.h b/beos/liblayout/layout-all.h new file mode 100644 index 000000000..b2e78df10 --- /dev/null +++ b/beos/liblayout/layout-all.h @@ -0,0 +1,35 @@ +#include "MApplication.h" +#include "MWindow.h" +#include "HGroup.h" +#include "VGroup.h" +#include "LayeredGroup.h" +#include "TabGroup.h" +#include "MBViewWrapper.h" +#include "MBorder.h" +#include "MButton.h" +#include "MCheckBox.h" +#include "MDividable.h" +#include "MDragBar.h" +#include "MEject.h" +#include "MFFWD.h" +#include "MListView.h" +#include "MMenuBar.h" +#include "MOutlineListView.h" +#include "MPictureButton.h" +#include "MPlayBW.h" +#include "MPlayFW.h" +#include "MPopup.h" +#include "MProgressBar.h" +#include "MRadioGroup.h" +#include "MRew.h" +#include "MScrollView.h" +#include "MSlider.h" +#include "MSplitter.h" +#include "MStop.h" +#include "MStringView.h" +#include "MTextControl.h" +#include "MTextView.h" +#include "MVolume.h" +#include "PropGadget.h" +#include "Space.h" +#include "SpinButton.h" diff --git a/beos/liblayout/layout.h b/beos/liblayout/layout.h new file mode 100644 index 000000000..772b251db --- /dev/null +++ b/beos/liblayout/layout.h @@ -0,0 +1,168 @@ +/* + + Lowest-level classes in liblayout + - minimax, used to store information about minimum size, maximum size, and weigth of objects + - MView, a class that knows how to layout itself + +*/ + +#ifndef _LAYOUT_H +#define _LAYOUT_H + +#if __POWERPC__ +#pragma simple_class_byval off +#endif + +#include <BeBuild.h> + +#if !defined(IMPEXPLIBLAYOUT) && defined(BUILDING_LIBLAYOUT) +#define IMPEXPLIBLAYOUT _EXPORT +#else +#define IMPEXPLIBLAYOUT _IMPORT +#endif + +#include <Rect.h> +#include <GraphicsDefs.h> +#include <stdlib.h> + +class BMessage; +class BFont; + +// use macro to make code slightly more readable +#define MVPTR(x) dynamic_cast<MView*>(x) + +enum fontspec +{ + M_PLAIN_FONT=0, + M_BOLD_FONT, + M_FIXED_FONT +}; + + +// this structure is exported from liblayout, and contains the version number +struct LAYOUT_VERSION_INFO +{ + uchar major; + uchar minor; + ushort patchlevel; +}; + +extern "C" LAYOUT_VERSION_INFO IMPEXPLIBLAYOUT LIBLAYOUT_VERSION; + + +class IMPEXPLIBLAYOUT minimax // Order now, by dialing the number on your screen! +{ +struct xypair { float x,y;}; + + public: xypair mini; + xypair maxi; + float weight; + + minimax(int minx=0,int miny=0, + int maxx=10000,int maxy=10000, + float wght=1.0); +}; + +class IMPEXPLIBLAYOUT MView +{ + protected: rgb_color FILL_COLOR; + rgb_color LOW_COLOR; + rgb_color HI_COLOR; + + // helper functions for archiving/unarchiving the MView + // part of MView hybrids + status_t archive(BMessage *); + status_t unarchive(BMessage *); + + public: minimax mpm; // currently active minimax (calculated from ct_mpm and environmental constraints) + minimax ct_mpm; // size specified at construction-time + ulong flags; // various flags + // upper 16 bits are reserve for liblayout-use + // bits 8-15 are reserved for per-class liblayout-use + // bits 0-7 are available + + MView(); + virtual ~MView(); + virtual minimax layoutprefs()=0; + virtual BRect layout(BRect rect)=0; + + // reload the font from one of the fonts in the font-array + virtual void reloadfont(BFont *font[]); + // get a BFont with the required fontspec + const BFont *getfont(fontspec font); + + // set the color of the MView + virtual void setcolor(rgb_color col, bool deep=true); + // this one calls the above function + void setcolor(uchar red, uchar green, uchar blue, bool deep=true); + rgb_color getcolor(); // get the base color (what is set through setcolor() ) + + private: + virtual void _expansionmview1(); + virtual void _expansionmview2(); + virtual void _expansionmview3(); + virtual void _expansionmview4(); + + uint32 _expansiondata[4]; +}; + + +// constants used in messaging all start with a '!' +#define M_POPUP_SELECTED '!pop' +#define M_CHECKBOX_SELECTED '!chk' +#define M_BUTTON_SELECTED '!but' +#define M_RADIO_SELECTED '!rad' +#define M_PLAYBW_SELECTED '!ylp' +#define M_PLAYFW_SELECTED '!ply' +#define M_FFWD_SELECTED '!fwd' +#define M_REW_SELECTED '!rwd' +#define M_STOP_SELECTED '!stp' +#define M_VOLUME_CHANGED '!vol' +#define M_EJECT_SELECTED '!ejt' +#define M_PREV_SELECTED '!prv' +#define M_NEXT_SELECTED '!nxt' +#define M_PROGRESSBAR_CLICKED '!pbc' +#define M_PROGRESSBAR_DRAGGED '!pbd' +#define M_PROGRESSBAR_RELEASED '!pbr' +#define M_ACTIVATE_LAYER '!lyr' + +// when sent to a window, it recalculates the entire window +#define M_RECALCULATE_SIZE '!rsz' + +// font-change message is understood by MWindow and MApplication, +// but is not generated by liblayout. +#define M_FONT_CHANGED '!FNT' + +extern IMPEXPLIBLAYOUT rgb_color M_FILL_COLOR; +extern IMPEXPLIBLAYOUT rgb_color M_LOW_COLOR; +extern IMPEXPLIBLAYOUT rgb_color M_HI_COLOR; +extern IMPEXPLIBLAYOUT rgb_color BLACK_COLOR; +extern IMPEXPLIBLAYOUT rgb_color WHITE_COLOR; + +void IMPEXPLIBLAYOUT SetDefaultColors(uchar red, uchar green, uchar blue); +void IMPEXPLIBLAYOUT SetDefaultColors(rgb_color cs); + +// misc flags +// note that not all controls responds to all flags + +enum{ + M_REPORT_IMMEDIATE= 0x00010000, // report first click on control + M_REPORT_REPEAT = 0x00020000, // report if control is clicked and held + M_REPORT_RELEASE= 0x00040000, // report release of button over control + M_REPORT_RELEASE_ALWAYS= 0x00080000, // always report release of button + M_REPORT_MASK= 0x000f0000, // all of the above + + // mostly for internal use, therefore not documented (yet) + M_USE_CALCULATED_MINX= 0x00100000, + M_USE_CALCULATED_MINY= 0x00200000, + M_USE_CALCULATED_MAXX= 0x00400000, + M_USE_CALCULATED_MAXY= 0x00800000, + M_NO_X_LEFTOVERS= 0x01000000, // don't add "leftover" space to this object + M_NO_Y_LEFTOVERS= 0x02000000, // don't add "leftover" space to this object + M_NO_COLOR_CHANGES= 0x20000000, // don't listen to color-drop messages + M_NO_FONT_CHANGES= 0x40000000, // don't listen to font-change messages + M_USE_FULL_SIZE = (int) 0x80000000 // don't respect max-size (set for grouping classes) +}; + + +#endif diff --git a/core/Ac3Dec.c b/core/Ac3Dec.c index d5430d49e..e1b027887 100644 --- a/core/Ac3Dec.c +++ b/core/Ac3Dec.c @@ -1,23 +1,18 @@ -/* $Id: Ac3Dec.c,v 1.4 2003/11/04 20:16:44 titer Exp $ +/* $Id: Ac3Dec.c,v 1.12 2004/01/16 19:04:03 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "Ac3Dec.h" -#include "Fifo.h" -#include "Work.h" +#include "HBInternal.h" -#include <a52dec/a52.h> +/* liba52 */ +#include "a52dec/a52.h" -/* Local prototypes */ -static int Ac3DecWork( HBWork * ); -static int GetBytes( HBAc3Dec *, int ); - -struct HBAc3Dec +typedef struct HBAc3Dec { HB_WORK_COMMON_MEMBERS - + HBHandle * handle; HBAudio * audio; @@ -35,9 +30,13 @@ struct HBAc3Dec int nextFrameSize; /* In bytes */ float position; HBBuffer * rawBuffer; -}; +} HBAc3Dec; + +/* Local prototypes */ +static int Ac3DecWork( HBWork * ); +static int GetBytes( HBAc3Dec *, int ); -HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio ) +HBWork * HBAc3DecInit( HBHandle * handle, HBAudio * audio ) { HBAc3Dec * a; if( !( a = malloc( sizeof( HBAc3Dec ) ) ) ) @@ -59,8 +58,15 @@ HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio ) /* Let it do the downmixing */ a->outFlags = A52_STEREO; - /* Lame wants samples from -32768 to 32768 */ - a->sampleLevel = 32768.0; + if( audio->codec == HB_CODEC_MP3 ) + /* Lame wants 16 bits samples */ + a->sampleLevel = 32768.0; + else if( audio->codec == HB_CODEC_AAC ) + /* Faac wants 24 bits samples */ + a->sampleLevel = 8388608.0; + else if( audio->codec == HB_CODEC_VORBIS ) + /* Vorbis wants FIXME bits samples */ + a->sampleLevel = 32768.0; a->ac3FrameSize = 0; a->ac3Buffer = NULL; @@ -69,13 +75,13 @@ HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio ) a->position = 0.0; a->rawBuffer = NULL; - return a; + return (HBWork*) a; } -void HBAc3DecClose( HBAc3Dec ** _a ) +void HBAc3DecClose( HBWork ** _a ) { - HBAc3Dec * a = *_a; - + HBAc3Dec * a = (HBAc3Dec*) *_a; + if( a->ac3Buffer ) HBBufferClose( &a->ac3Buffer ); if( a->rawBuffer ) HBBufferClose( &a->rawBuffer ); a52_free( a->state ); @@ -89,7 +95,7 @@ static int Ac3DecWork( HBWork * w ) { HBAc3Dec * a = (HBAc3Dec*) w; HBAudio * audio = a->audio; - + int didSomething = 0; /* Push decoded buffer */ @@ -135,7 +141,7 @@ static int Ac3DecWork( HBWork * w ) sample_t * samples; HBBuffer * rawBuffer; int i; - + if( GetBytes( a, a->nextFrameSize ) ) { didSomething = 1; @@ -153,6 +159,9 @@ static int Ac3DecWork( HBWork * w ) /* 6 blocks per frame, 256 samples per block, 2 channels */ rawBuffer = HBBufferInit( 12 * 256 * sizeof( float ) ); rawBuffer->position = a->position; + rawBuffer->samples = 6 * 256; + rawBuffer->left = (float*) rawBuffer->data; + rawBuffer->right = rawBuffer->left + 6 * 256; for( i = 0; i < 6; i++ ) { @@ -163,41 +172,34 @@ static int Ac3DecWork( HBWork * w ) samples = a52_samples( a->state ); /* Copy left channel data */ - memcpy( rawBuffer->data + i * 256 * sizeof( float ), - samples, + memcpy( rawBuffer->left + i * 256, samples, 256 * sizeof( float ) ); /* Copy right channel data */ - memcpy( rawBuffer->data + ( 6 + i ) * 256 * sizeof( float ), - samples + 256, + memcpy( rawBuffer->right + i * 256, samples + 256, 256 * sizeof( float ) ); } a->rawBuffer = rawBuffer; } - + return didSomething; } static int GetBytes( HBAc3Dec * a, int size ) { int i; - + while( a->ac3FrameSize < size ) { if( !a->ac3Buffer ) { - if( !( a->ac3Buffer = HBFifoPop( a->audio->ac3Fifo ) ) ) + if( !( a->ac3Buffer = HBFifoPop( a->audio->inFifo ) ) ) { return 0; } a->ac3BufferPos = 0; a->position = a->ac3Buffer->position; - - if( a->ac3Buffer->last ) - { - HBDone( a->handle ); - } } i = MIN( size - a->ac3FrameSize, diff --git a/core/Ac3Dec.h b/core/Ac3Dec.h deleted file mode 100644 index a1ecaff66..000000000 --- a/core/Ac3Dec.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: Ac3Dec.h,v 1.1 2003/11/03 12:08:00 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_AC3_DEC_H -#define HB_AC3_DEC_H - -#include "HandBrakeInternal.h" - -HBAc3Dec * HBAc3DecInit( HBHandle *, HBAudio * ); -void HBAc3DecClose( HBAc3Dec ** ); - -#endif diff --git a/core/AviMux.c b/core/AviMux.c index ca34d3cab..71238425e 100644 --- a/core/AviMux.c +++ b/core/AviMux.c @@ -1,42 +1,38 @@ -/* $Id: AviMux.c,v 1.6 2003/11/13 01:18:52 titer Exp $ +/* $Id: AviMux.c,v 1.15 2004/02/18 17:07:20 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "AviMux.h" -#include "Fifo.h" -#include "Thread.h" +#include "HBInternal.h" -/* Local structures */ -typedef struct AviMainHeader AviMainHeader; -typedef struct AviStreamHeader AviStreamHeader; -typedef struct BitmapInfo BitmapInfo; -typedef struct WaveFormatEx WaveFormatEx; +int64_t videoFrames; +int64_t videoBytes; +int64_t audioFrames; +int64_t audioBytes; /* Local prototypes */ static void AviMuxThread( void * ); static void InitAviHeaders( HBAviMux * ); -static void AddChunk( HBAviMux *, HBBuffer **, uint32_t, - AviStreamHeader * ); +static void AddChunk( HBAviMux *, HBBuffer *, uint32_t, + HBAviStreamHeader * ); static void AddIndex( HBAviMux * ); static void WriteInt8( FILE *, uint8_t ); static void WriteInt16( FILE *, uint16_t ); static void WriteInt32( FILE *, uint32_t ); static void WriteBuffer( FILE *, HBBuffer * ); -static void WriteMainHeader( FILE *, AviMainHeader * ); -static void WriteStreamHeader( FILE *, AviStreamHeader * ); -static void WriteBitmapInfo( FILE *, BitmapInfo * ); -static void WriteWaveFormatEx( FILE *, WaveFormatEx * ); +static void WriteMainHeader( FILE *, HBAviMainHeader * ); +static void WriteStreamHeader( FILE *, HBAviStreamHeader * ); +static void WriteHBBitmapInfo( FILE *, HBBitmapInfo * ); +static void WriteHBWaveFormatEx( FILE *, HBWaveFormatEx * ); static void IndexAddInt32( HBBuffer * buffer, uint32_t ); -static HBBuffer * Pop( HBAviMux *, HBFifo * ); #define AVIF_HASINDEX 0x10 #define AVIIF_KEYFRAME 0x10 #define FOURCC(a) ((a[3]<<24)|(a[2]<<16)|(a[1]<<8)|a[0]) /* Structures definitions */ -struct __attribute__((__packed__)) AviMainHeader +struct __attribute__((__packed__)) HBAviMainHeader { uint32_t FourCC; uint32_t BytesCount; @@ -53,7 +49,7 @@ struct __attribute__((__packed__)) AviMainHeader uint32_t Reserved[4]; }; -struct __attribute__((__packed__)) AviStreamHeader +struct __attribute__((__packed__)) HBAviStreamHeader { uint32_t FourCC; uint32_t BytesCount; @@ -76,7 +72,7 @@ struct __attribute__((__packed__)) AviStreamHeader int16_t Bottom; }; -struct __attribute__((__packed__)) BitmapInfo +struct __attribute__((__packed__)) HBBitmapInfo { uint32_t FourCC; uint32_t BytesCount; @@ -91,13 +87,9 @@ struct __attribute__((__packed__)) BitmapInfo uint32_t YPelsPerMeter; uint32_t ClrUsed; uint32_t ClrImportant; - uint8_t Blue; - uint8_t Green; - uint8_t Red; - uint8_t Reserved; }; -struct __attribute__((__packed__)) WaveFormatEx +struct __attribute__((__packed__)) HBWaveFormatEx { uint32_t FourCC; uint32_t BytesCount; @@ -121,28 +113,18 @@ struct HBAviMux { HBHandle * handle; HBTitle * title; - HBAudio * audio; - HBAudio * optAudio; - - AviMainHeader mainHeader; - AviStreamHeader videoHeader; - BitmapInfo videoFormat; - AviStreamHeader audioHeader; - WaveFormatEx audioFormat; - AviStreamHeader optAudioHeader; - WaveFormatEx optAudioFormat; /* Data size in bytes, not including headers */ unsigned size; + FILE * file; HBBuffer * index; - int die; + volatile int die; HBThread * thread; }; -HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title, - HBAudio * audio, HBAudio * optAudio ) +HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title ) { HBAviMux * a; if( !( a = malloc( sizeof( HBAviMux ) ) ) ) @@ -153,8 +135,11 @@ HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title, a->handle = handle; a->title = title; - a->audio = audio; - a->optAudio = optAudio; + + videoFrames = 0; + videoBytes = 0; + audioFrames = 0; + audioBytes = 0; a->size = 0; a->file = NULL; @@ -170,9 +155,23 @@ HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title, void HBAviMuxClose( HBAviMux ** _a ) { HBAviMux * a = *_a; + FILE * file; + long size; a->die = 1; HBThreadClose( &a->thread ); + + file = fopen( a->title->file, "r" ); + fseek( file, 0, SEEK_END ); + size = ftell( file ); + fclose( file ); + + HBLog( "HBAviMux: videoFrames=%lld, %lld bytes", videoFrames, videoBytes ); + HBLog( "HBAviMux: audioFrames=%lld, %lld bytes", audioFrames, audioBytes ); + HBLog( "HBAviMux: overhead=%.2f bytes / frame", + ( (float) size - videoBytes - audioBytes ) / + ( videoFrames + audioFrames ) ); + free( a ); *_a = NULL; @@ -180,14 +179,13 @@ void HBAviMuxClose( HBAviMux ** _a ) static void AviMuxThread( void * _a ) { - HBAviMux * a = (HBAviMux*) _a; - HBTitle * title = a->title; - HBAudio * audio = a->audio; - HBAudio * optAudio = a->optAudio; + HBAviMux * a = (HBAviMux*) _a; + HBTitle * title = a->title; + int audioCount = HBListCount( title->ripAudioList ); - HBBuffer * videoBuffer = NULL; - HBBuffer * audioBuffer = NULL; - HBBuffer * optAudioBuffer = NULL; + HBAudio * audio; + HBBuffer * buffer; + int i; /* Open destination file */ HBLog( "HBAviMux: opening %s", title->file ); @@ -198,21 +196,25 @@ static void AviMuxThread( void * _a ) return; } - /* Get a buffer for each track */ - videoBuffer = Pop( a, title->mpeg4Fifo ); - audioBuffer = Pop( a, audio->mp3Fifo ); - if( optAudio ) + /* Wait until we have one encoded frame for each track */ + while( !a->die && !HBFifoSize( title->outFifo ) ) { - optAudioBuffer = Pop( a, optAudio->mp3Fifo ); + HBSnooze( 10000 ); + } + for( i = 0; i < audioCount; i++ ) + { + audio = HBListItemAt( title->ripAudioList, i ); + while( !a->die && !HBFifoSize( audio->outFifo ) ) + { + HBSnooze( 10000 ); + } } - /* Failed ? Then forget it */ - if( !videoBuffer || !audioBuffer || - ( optAudio && !optAudioBuffer ) ) + if( a->die ) { fclose( a->file ); a->file = NULL; - + HBLog( "HBAviMux: deleting %s", title->file ); unlink( title->file ); return; @@ -222,48 +224,56 @@ static void AviMuxThread( void * _a ) for( ;; ) { - /* Get a buffer for each track */ - if( !videoBuffer ) - { - videoBuffer = Pop( a, title->mpeg4Fifo ); - } - if( !audioBuffer ) + /* Wait until we have one encoded frame for each track */ + if( !HBFifoWait( title->outFifo ) ) { - audioBuffer = Pop( a, audio->mp3Fifo ); + a->die = 1; } - if( optAudio && !optAudioBuffer ) + for( i = 0; i < audioCount; i++ ) { - optAudioBuffer = Pop( a, optAudio->mp3Fifo ); + audio = HBListItemAt( title->ripAudioList, i ); + if( !HBFifoWait( audio->outFifo ) ) + { + a->die = 1; + break; + } } - if( !videoBuffer && !audioBuffer && !optAudioBuffer ) + if( a->die ) { - /* Couldn't get anything -> must exit NOW */ break; } /* Interleave frames in the same order than they were in the original MPEG stream */ - if( videoBuffer && - ( !audioBuffer || - videoBuffer->position < audioBuffer->position ) && - ( !optAudioBuffer || - videoBuffer->position < optAudioBuffer->position ) ) + audio = NULL; + for( i = 0; i < audioCount; i++ ) { - AddChunk( a, &videoBuffer, FOURCC( "00dc" ), - &a->videoHeader ); + HBAudio * otherAudio; + otherAudio = HBListItemAt( title->ripAudioList, i ); + if( !audio || HBFifoPosition( otherAudio->outFifo ) < + HBFifoPosition( audio->outFifo ) ) + { + audio = otherAudio; + } } - else if( audioBuffer && - ( !optAudioBuffer || - audioBuffer->position < optAudioBuffer->position ) ) + + if( audio == NULL || + HBFifoPosition( title->outFifo ) < HBFifoPosition( audio->outFifo ) ) { - AddChunk( a, &audioBuffer, FOURCC( "01wb" ), - &a->audioHeader ); + buffer = HBFifoPop( title->outFifo ); + AddChunk( a, buffer, FOURCC( "00dc" ), title->aviVideoHeader ); + videoFrames++; + videoBytes += buffer->size; + HBBufferClose( &buffer ); } else { - AddChunk( a, &optAudioBuffer, FOURCC( "02wb" ), - &a->optAudioHeader ); + buffer = HBFifoPop( audio->outFifo ); + AddChunk( a, buffer, audio->aviFourCC, audio->aviAudioHeader ); + audioFrames++; + audioBytes += buffer->size; + HBBufferClose( &buffer ); } } @@ -275,49 +285,57 @@ static void AviMuxThread( void * _a ) static void InitAviHeaders( HBAviMux * a ) { - HBTitle * title = a->title; - HBAudio * audio = a->audio; - HBAudio * optAudio = a->optAudio; - AviMainHeader * mainHeader = &a->mainHeader; - AviStreamHeader * videoHeader = &a->videoHeader; - BitmapInfo * videoFormat = &a->videoFormat; - AviStreamHeader * audioHeader = &a->audioHeader; - WaveFormatEx * audioFormat = &a->audioFormat; - AviStreamHeader * optAudioHeader = &a->optAudioHeader; - WaveFormatEx * optAudioFormat = &a->optAudioFormat; - FILE * file = a->file; - int hdrlBytes; - int i; + HBTitle * title = a->title; + FILE * file = a->file; + int audioCount = HBListCount( title->ripAudioList ); + + HBAudio * audio; + HBAviMainHeader * mainHeader; + HBAviStreamHeader * videoHeader; + HBBitmapInfo * videoFormat; + HBAviStreamHeader * audioHeader; + HBWaveFormatEx * audioFormat; + int hdrlBytes; + int i; /* AVI main header */ - memset( mainHeader, 0, sizeof( AviMainHeader ) ); + mainHeader = calloc( sizeof( HBAviMainHeader ), 1 ); + mainHeader->FourCC = FOURCC( "avih" ); - mainHeader->BytesCount = sizeof( AviMainHeader ) - 8; + mainHeader->BytesCount = sizeof( HBAviMainHeader ) - 8; mainHeader->MicroSecPerFrame = (uint64_t) 1000000 * title->rateBase / title->rate; - mainHeader->Streams = optAudio ? 3 : 2; + mainHeader->Streams = 1 + audioCount; mainHeader->Width = title->outWidth; mainHeader->Height = title->outHeight; + title->aviMainHeader = mainHeader; + /* Video stream header */ - memset( videoHeader, 0, sizeof( AviStreamHeader ) ); + videoHeader = calloc( sizeof( HBAviStreamHeader ), 1 ); + videoHeader->FourCC = FOURCC( "strh" ); - videoHeader->BytesCount = sizeof( AviStreamHeader ) - 8; + videoHeader->BytesCount = sizeof( HBAviStreamHeader ) - 8; videoHeader->Type = FOURCC( "vids" ); - + if( title->codec == HB_CODEC_FFMPEG ) videoHeader->Handler = FOURCC( "divx" ); else if( title->codec == HB_CODEC_XVID ) videoHeader->Handler = FOURCC( "xvid" ); - + else if( title->codec == HB_CODEC_X264 ) + videoHeader->Handler = FOURCC( "H264" ); + videoHeader->Scale = title->rateBase; videoHeader->Rate = title->rate; + title->aviVideoHeader = videoHeader; + /* Video stream format */ - memset( videoFormat, 0, sizeof( BitmapInfo ) ); + videoFormat = calloc( sizeof( HBBitmapInfo ), 1 ); + videoFormat->FourCC = FOURCC( "strf" ); - videoFormat->BytesCount = sizeof( BitmapInfo ) - 8; - videoFormat->Size = sizeof( BitmapInfo ) - 8; + videoFormat->BytesCount = sizeof( HBBitmapInfo ) - 8; + videoFormat->Size = sizeof( HBBitmapInfo ) - 8; videoFormat->Width = title->outWidth; videoFormat->Height = title->outHeight; videoFormat->Planes = 1; @@ -326,66 +344,51 @@ static void InitAviHeaders( HBAviMux * a ) videoFormat->Compression = FOURCC( "DX50" ); else if( title->codec == HB_CODEC_XVID ) videoFormat->Compression = FOURCC( "XVID" ); + else if( title->codec == HB_CODEC_X264 ) + videoFormat->Compression = FOURCC( "H264" ); - /* Audio stream header */ - memset( audioHeader, 0, sizeof( AviStreamHeader ) ); - audioHeader->FourCC = FOURCC( "strh" ); - audioHeader->BytesCount = sizeof( AviStreamHeader ) - 8; - audioHeader->Type = FOURCC( "auds" ); - audioHeader->InitialFrames = 1; - audioHeader->Scale = 1152; - audioHeader->Rate = audio->outSampleRate; - audioHeader->Quality = 0xFFFFFFFF; - - /* Audio stream format */ - memset( audioFormat, 0, sizeof( WaveFormatEx ) ); - audioFormat->FourCC = FOURCC( "strf" ); - audioFormat->BytesCount = sizeof( WaveFormatEx ) - 8; - audioFormat->FormatTag = 0x55; - audioFormat->Channels = 2; - audioFormat->SamplesPerSec = audio->outSampleRate; - audioFormat->AvgBytesPerSec = audio->outBitrate * 1024 / 8; - audioFormat->BlockAlign = 1152; - audioFormat->Size = 12; - audioFormat->Id = 1; - audioFormat->Flags = 2; - audioFormat->BlockSize = 1152; - audioFormat->FramesPerBlock = 1; - audioFormat->CodecDelay = 1393; - - if( optAudio ) + title->aviVideoFormat = videoFormat; + + for( i = 0; i < audioCount; i++ ) { - /* optAudio stream header */ - memset( optAudioHeader, 0, sizeof( AviStreamHeader ) ); - optAudioHeader->FourCC = FOURCC( "strh" ); - optAudioHeader->BytesCount = sizeof( AviStreamHeader ) - 8; - optAudioHeader->Type = FOURCC( "auds" ); - optAudioHeader->InitialFrames = 1; - optAudioHeader->Scale = 1152; - optAudioHeader->Rate = optAudio->outSampleRate; - optAudioHeader->Quality = 0xFFFFFFFF; - - /* optAudio stream format */ - memset( optAudioFormat, 0, sizeof( WaveFormatEx ) ); - optAudioFormat->FourCC = FOURCC( "strf" ); - optAudioFormat->BytesCount = sizeof( WaveFormatEx ) - 8; - optAudioFormat->FormatTag = 0x55; - optAudioFormat->Channels = 2; - optAudioFormat->SamplesPerSec = optAudio->outSampleRate; - optAudioFormat->AvgBytesPerSec = optAudio->outBitrate * 1024 / 8; - optAudioFormat->BlockAlign = 1152; - optAudioFormat->Size = 12; - optAudioFormat->Id = 1; - optAudioFormat->Flags = 2; - optAudioFormat->BlockSize = 1152; - optAudioFormat->FramesPerBlock = 1; - optAudioFormat->CodecDelay = 1393; + audio = HBListItemAt( title->ripAudioList, i ); + + /* Audio stream header */ + audioHeader = calloc( sizeof( HBAviStreamHeader ), 1 ); + + audioHeader->FourCC = FOURCC( "strh" ); + audioHeader->BytesCount = sizeof( HBAviStreamHeader ) - 8; + audioHeader->Type = FOURCC( "auds" ); + audioHeader->InitialFrames = 1; + audioHeader->Scale = 1152; + audioHeader->Rate = audio->outSampleRate; + audioHeader->Quality = 0xFFFFFFFF; + + audio->aviAudioHeader = audioHeader; + + /* Audio stream format */ + audioFormat = calloc( sizeof( HBWaveFormatEx ), 1 ); + + audioFormat->FourCC = FOURCC( "strf" ); + audioFormat->BytesCount = sizeof( HBWaveFormatEx ) - 8; + audioFormat->FormatTag = 0x55; + audioFormat->Channels = 2; + audioFormat->SamplesPerSec = audio->outSampleRate; + audioFormat->AvgBytesPerSec = audio->outBitrate * 1024 / 8; + audioFormat->BlockAlign = 1152; + audioFormat->Size = 12; + audioFormat->Id = 1; + audioFormat->Flags = 2; + audioFormat->BlockSize = 1152; + audioFormat->FramesPerBlock = 1; + audioFormat->CodecDelay = 1393; + + audio->aviAudioFormat = audioFormat; } - hdrlBytes = 4 + sizeof( AviMainHeader ) + - ( optAudio ? 3 : 2 ) * ( 12 + sizeof( AviStreamHeader ) ) + - sizeof( BitmapInfo ) + - ( optAudio ? 2 : 1 ) * sizeof( WaveFormatEx ); + hdrlBytes = 4 + sizeof( HBAviMainHeader ) + ( 1 + audioCount ) * + ( 12 + sizeof( HBAviStreamHeader ) ) + sizeof( HBBitmapInfo ) + + audioCount * sizeof( HBWaveFormatEx ); /* Here we really start to write into the file */ @@ -395,28 +398,31 @@ static void InitAviHeaders( HBAviMux * a ) WriteInt32( file, FOURCC( "LIST" ) ); WriteInt32( file, hdrlBytes ); WriteInt32( file, FOURCC( "hdrl" ) ); - WriteMainHeader( file, mainHeader ); + WriteMainHeader( file, title->aviMainHeader ); WriteInt32( file, FOURCC( "LIST" ) ); - WriteInt32( file, 4 + sizeof( AviStreamHeader ) + - sizeof( BitmapInfo ) ); + WriteInt32( file, 4 + sizeof( HBAviStreamHeader ) + + sizeof( HBBitmapInfo ) ); WriteInt32( file, FOURCC( "strl" ) ); - WriteStreamHeader( file, videoHeader ); - WriteBitmapInfo( file, videoFormat ); - WriteInt32( file, FOURCC( "LIST" ) ); - WriteInt32( file, 4 + sizeof( AviStreamHeader ) + - sizeof( WaveFormatEx ) ); - WriteInt32( file, FOURCC( "strl" ) ); - WriteStreamHeader( file, audioHeader ); - WriteWaveFormatEx( file, audioFormat ); - if( optAudio ) + WriteStreamHeader( file, title->aviVideoHeader ); + WriteHBBitmapInfo( file, title->aviVideoFormat ); + + for( i = 0; i < audioCount; i++ ) { + char fourCC[5]; + + audio = HBListItemAt( title->ripAudioList, i ); + + snprintf( fourCC, 5, "%02dwb", i + 1 ); + audio->aviFourCC = FOURCC( fourCC ); + WriteInt32( file, FOURCC( "LIST" ) ); - WriteInt32( file, 4 + sizeof( AviStreamHeader ) + - sizeof( WaveFormatEx ) ); + WriteInt32( file, 4 + sizeof( HBAviStreamHeader ) + + sizeof( HBWaveFormatEx ) ); WriteInt32( file, FOURCC( "strl" ) ); - WriteStreamHeader( file, optAudioHeader ); - WriteWaveFormatEx( file, optAudioFormat ); + WriteStreamHeader( file, audio->aviAudioHeader ); + WriteHBWaveFormatEx( file, audio->aviAudioFormat ); } + WriteInt32( file, FOURCC( "JUNK" ) ); WriteInt32( file, 2008 - hdrlBytes ); for( i = 0; i < 2008 - hdrlBytes; i++ ) @@ -428,11 +434,14 @@ static void InitAviHeaders( HBAviMux * a ) WriteInt32( file, FOURCC( "movi" ) ); } -static void AddChunk( HBAviMux * a, HBBuffer ** _buffer, - uint32_t fourCC, AviStreamHeader * header ) +static void AddChunk( HBAviMux * a, HBBuffer * buffer, + uint32_t fourCC, HBAviStreamHeader * header ) { - HBBuffer * buffer = *_buffer; - + HBTitle * title = a->title; + + HBAudio * audio; + int i; + /* Update index */ IndexAddInt32( a->index, fourCC ); IndexAddInt32( a->index, buffer->keyFrame ? AVIIF_KEYFRAME : 0 ); @@ -459,28 +468,28 @@ static void AddChunk( HBAviMux * a, HBBuffer ** _buffer, fseek( a->file, 4, SEEK_SET ); WriteInt32( a->file, 2040 + a->size ); - /* AviStreamHeader's length */ + /* HBAviStreamHeader's lengths */ fseek( a->file, 140, SEEK_SET ); - WriteInt32( a->file, a->videoHeader.Length ); - fseek( a->file, 268, SEEK_SET ); - WriteInt32( a->file, a->audioHeader.Length ); - if( a->optAudio ) + WriteInt32( a->file, title->aviVideoHeader->Length ); + + for( i = 0; i < HBListCount( title->ripAudioList ); i++ ) { - fseek( a->file, 382, SEEK_SET ); - WriteInt32( a->file, a->optAudioHeader.Length ); + audio = (HBAudio*) HBListItemAt( title->ripAudioList, i ); + fseek( a->file, 268 + i * 114, SEEK_SET ); + WriteInt32( a->file, audio->aviAudioHeader->Length ); } /* movi size */ fseek( a->file, 2040, SEEK_SET ); WriteInt32( a->file, 4 + a->size ); - - HBBufferClose( _buffer ); } static void AddIndex( HBAviMux * a ) { + HBTitle * title = a->title; + fseek( a->file, 0, SEEK_END ); - + WriteInt32( a->file, FOURCC( "idx1" ) ); WriteInt32( a->file, a->index->size ); WriteBuffer( a->file, a->index ); @@ -488,9 +497,9 @@ static void AddIndex( HBAviMux * a ) a->size += 8 + a->index->size; fseek( a->file, 4, SEEK_SET ); WriteInt32( a->file, 2040 + a->size ); - a->mainHeader.Flags |= AVIF_HASINDEX; + title->aviMainHeader->Flags |= AVIF_HASINDEX; fseek( a->file, 24, SEEK_SET ); - WriteMainHeader( a->file, &a->mainHeader ); + WriteMainHeader( a->file, title->aviMainHeader ); } static void WriteInt8( FILE * file, uint8_t val ) @@ -517,7 +526,7 @@ static void WriteBuffer( FILE * file, HBBuffer * buffer ) fwrite( buffer->data, buffer->size, 1, file ); } -static void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo ) +static void WriteHBBitmapInfo( FILE * file, HBBitmapInfo * bitmapInfo ) { WriteInt32( file, bitmapInfo->FourCC ); WriteInt32( file, bitmapInfo->BytesCount ); @@ -532,13 +541,15 @@ static void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo ) WriteInt32( file, bitmapInfo->YPelsPerMeter ); WriteInt32( file, bitmapInfo->ClrUsed ); WriteInt32( file, bitmapInfo->ClrImportant ); +#if 0 WriteInt8( file, bitmapInfo->Blue ); WriteInt8( file, bitmapInfo->Green ); WriteInt8( file, bitmapInfo->Red ); WriteInt8( file, bitmapInfo->Reserved ); +#endif } -static void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx ) +static void WriteHBWaveFormatEx( FILE * file, HBWaveFormatEx * waveFormatEx ) { WriteInt32( file, waveFormatEx->FourCC ); WriteInt32( file, waveFormatEx->BytesCount ); @@ -556,7 +567,7 @@ static void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx ) WriteInt16( file, waveFormatEx->CodecDelay ); } -static void WriteMainHeader( FILE * file, AviMainHeader * mainHeader ) +static void WriteMainHeader( FILE * file, HBAviMainHeader * mainHeader ) { WriteInt32( file, mainHeader->FourCC ); WriteInt32( file, mainHeader->BytesCount ); @@ -576,7 +587,7 @@ static void WriteMainHeader( FILE * file, AviMainHeader * mainHeader ) WriteInt32( file, mainHeader->Reserved[3] ); } -static void WriteStreamHeader( FILE * file, AviStreamHeader * streamHeader ) +static void WriteStreamHeader( FILE * file, HBAviStreamHeader * streamHeader ) { WriteInt32( file, streamHeader->FourCC ); WriteInt32( file, streamHeader->BytesCount ); @@ -614,27 +625,3 @@ static void IndexAddInt32( HBBuffer * b, uint32_t val ) b->data[b->size++] = val >> 24; } -static HBBuffer * Pop( HBAviMux * a, HBFifo * fifo ) -{ - HBBuffer * buffer; - - for( ;; ) - { - HBCheckPaused( a->handle ); - - if( ( buffer = HBFifoPop( fifo ) ) ) - { - return buffer; - } - - if( a->die ) - { - break; - } - - HBSnooze( 10000 ); - } - - return NULL; -} - diff --git a/core/AviMux.h b/core/AviMux.h deleted file mode 100644 index 1fccbe971..000000000 --- a/core/AviMux.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: AviMux.h,v 1.1 2003/11/03 12:08:00 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_AVI_MUX_H -#define HB_AVI_MUX_H - -#include "HandBrakeInternal.h" - -HBAviMux * HBAviMuxInit( HBHandle *, HBTitle *, HBAudio *, HBAudio * ); -void HBAviMuxClose( HBAviMux ** ); - -#endif diff --git a/core/DVDRead.c b/core/DVDRead.c index 58e8f1031..f90660948 100644 --- a/core/DVDRead.c +++ b/core/DVDRead.c @@ -1,18 +1,17 @@ -/* $Id: DVDRead.c,v 1.4 2003/11/06 13:03:19 titer Exp $ +/* $Id: DVDRead.c,v 1.9 2004/01/16 19:04:03 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "DVDRead.h" -#include "Fifo.h" -#include "Thread.h" +#include "HBInternal.h" -#include <dvdread/ifo_types.h> -#include <dvdplay/dvdplay.h> -#include <dvdplay/info.h> -#include <dvdplay/state.h> -#include <dvdplay/nav.h> +/* libdvdplay */ +#include "dvdread/ifo_types.h" +#include "dvdplay/dvdplay.h" +#include "dvdplay/info.h" +#include "dvdplay/state.h" +#include "dvdplay/nav.h" /* Local prototypes */ static void DVDReadThread( void * ); @@ -22,30 +21,21 @@ static int Push( HBDVDRead *, HBFifo * fifo, HBBuffer ** buffer ); struct HBDVDRead { - HBHandle * handle; - - dvdplay_ptr vmg; - HBTitle * title; - HBAudio * audio; - HBAudio * optAudio; - int beginPosition; - int endPosition; - int pass; - HBBuffer * psBuffer; - HBList * esBufferList; - HBBuffer * videoBuf; - HBBuffer * audioBuf; - HBBuffer * optAudioBuf; - int videoStart; - int audioStart; - int optAudioStart; - - int die; - HBThread * thread; + HBHandle * handle; + + dvdplay_ptr vmg; + HBTitle * title; + int beginPosition; + int endPosition; + int pass; + HBBuffer * psBuffer; + HBList * esBufferList; + + volatile int die; + HBThread * thread; }; -HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * t, - HBAudio * a1, HBAudio * a2 ) +HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * title ) { HBDVDRead * d; if( !( d = malloc( sizeof( HBDVDRead ) ) ) ) @@ -57,20 +47,12 @@ HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * t, /* Initializations */ d->handle = handle; d->vmg = NULL; - d->title = t; - d->audio = a1; - d->optAudio = a2; + d->title = title; d->beginPosition = 0; d->endPosition = 0; d->pass = 0; d->psBuffer = NULL; d->esBufferList = HBListInit(); - d->videoBuf = NULL; - d->audioBuf = NULL; - d->optAudioBuf = NULL; - d->videoStart = -1; - d->audioStart = -1; - d->optAudioStart = -1; /* Launch the thread */ d->die = 0; @@ -83,13 +65,13 @@ HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * t, void HBDVDReadClose( HBDVDRead ** _d ) { HBBuffer * buffer; - + HBDVDRead * d = *_d; - + /* Stop the thread */ d->die = 1; HBThreadClose( &d->thread ); - + /* Clean up */ while( ( buffer = (HBBuffer*) HBListItemAt( d->esBufferList, 0 ) ) ) { @@ -98,72 +80,58 @@ void HBDVDReadClose( HBDVDRead ** _d ) } HBListClose( &d->esBufferList ) ; free( d ); - + (*_d) = NULL; } static void DVDReadThread( void * _d ) { - HBDVDRead * d = (HBDVDRead*) _d; + HBDVDRead * d = (HBDVDRead*) _d; + HBTitle * title = d->title; + uint8_t dummy[DVD_VIDEO_LB_LEN]; int i; /* Open the device */ - d->vmg = dvdplay_open( d->title->device, NULL, NULL ); + d->vmg = dvdplay_open( title->device, NULL, NULL ); if( !d->vmg ) { HBLog( "HBDVDRead: dvdplay_open() failed" ); HBErrorOccured( d->handle, HB_ERROR_DVD_OPEN ); return; - } - + } + /* Open the title */ - dvdplay_start( d->vmg, d->title->index ); + dvdplay_start( d->vmg, title->index ); d->beginPosition = dvdplay_title_first( d->vmg ); d->endPosition = dvdplay_title_end( d->vmg ); - + HBLog( "HBDVDRead: starting, blocks: %d to %d", d->beginPosition, d->endPosition ); - + /* Lalala */ dvdplay_read( d->vmg, dummy, 1 ); - + /* Do the job */ - for( i = 0; i < ( d->title->twoPass ? 2 : 1 ); i++ ) + for( i = 0; i < ( title->twoPass ? 2 : 1 ); i++ ) { dvdplay_seek( d->vmg, 0 ); - + HBLog( "HBDVDRead: starting pass %d of %d", i + 1, - d->title->twoPass ? 2 : 1 ); - - d->pass = d->title->twoPass ? ( i + 1 ) : 0; + title->twoPass ? 2 : 1 ); + + d->pass = title->twoPass ? ( i + 1 ) : 0; if( !DoPass( d ) ) { break; - } - } + } + } - /* Flag the latest buffers so we know when we're done */ if( !d->die ) { HBLog( "HBDVDRead: done" ); - - if( d->videoBuf ) - { - d->videoBuf->last = 1; - Push( d, d->title->mpeg2Fifo, &d->videoBuf ); - } - if( d->audioBuf ) - { - d->audioBuf->last = 1; - Push( d, d->audio->ac3Fifo, &d->audioBuf ); - } - if( d->optAudioBuf ) - { - d->optAudioBuf->last = 1; - Push( d, d->optAudio->ac3Fifo, &d->optAudioBuf ); - } + HBDone( d->handle ); } /* Clean up */ @@ -180,20 +148,20 @@ static int DoPass( HBDVDRead * d ) d->psBuffer = HBBufferInit( DVD_VIDEO_LB_LEN ); d->psBuffer->position = (float) i / ( d->endPosition - d->beginPosition ); - + if( d->pass ) { d->psBuffer->position /= 2; - + if( d->pass == 2 ) { d->psBuffer->position += 0.5; } } d->psBuffer->pass = d->pass; - + if( dvdplay_read( d->vmg, d->psBuffer->data, 1 ) < 0 ) - { + { HBLog( "HBDVDRead: dvdplay_read() failed" ); HBErrorOccured( d->handle, HB_ERROR_DVD_READ ); HBBufferClose( &d->psBuffer ); @@ -211,7 +179,11 @@ static int DoPass( HBDVDRead * d ) static int Demux( HBDVDRead * d ) { + HBTitle * title = d->title; + + HBAudio * audio; HBBuffer * esBuffer; + int i; /* Demux */ HBPStoES( &d->psBuffer, d->esBufferList ); @@ -229,72 +201,48 @@ static int Demux( HBDVDRead * d ) if( esBuffer->streamId == 0xE0 ) { - if( d->videoStart < 0 ) + if( title->start < 0 ) { - d->videoStart = esBuffer->pts / 90; + title->start = esBuffer->pts / 90; HBLog( "HBDVDRead: got first 0xE0 packet (%d)", - d->videoStart ); + title->start ); } - if( d->videoBuf ) + HBListRemove( d->esBufferList, esBuffer ); + if( !Push( d, title->inFifo, &esBuffer ) ) { - d->videoBuf->last = 0; - if( !Push( d, d->title->mpeg2Fifo, &d->videoBuf ) ) - { - return 0; - } + return 0; } - - HBListRemove( d->esBufferList, esBuffer ); - d->videoBuf = esBuffer; + continue; } - else if( esBuffer->streamId == d->audio->id ) - { - if( d->audioStart < 0 ) - { - d->audioStart = esBuffer->pts / 90; - HBLog( "HBDVDRead: got first 0x%x packet (%d)", - d->audio->id, d->audioStart ); - d->audio->delay = d->audioStart - d->videoStart; - } + for( i = 0; i < HBListCount( title->ripAudioList ); i++ ) + { + audio = (HBAudio*) HBListItemAt( title->ripAudioList, i ); - if( d->audioBuf ) + if( esBuffer->streamId != audio->id ) { - d->audioBuf->last = 0; - if( !Push( d, d->audio->ac3Fifo, &d->audioBuf ) ) - { - return 0; - } + continue; } - HBListRemove( d->esBufferList, esBuffer ); - d->audioBuf = esBuffer; - } - else if( d->optAudio && esBuffer->streamId == d->optAudio->id ) - { - if( d->optAudioStart < 0 ) + if( audio->start < 0 ) { - d->optAudioStart = esBuffer->pts / 90; + audio->start = esBuffer->pts / 90; HBLog( "HBDVDRead: got first 0x%x packet (%d)", - d->optAudio->id, d->optAudioStart ); + audio->id, audio->start ); - d->optAudio->delay = d->optAudioStart - d->videoStart; + audio->delay = audio->start - title->start; } - if( d->optAudioBuf ) + HBListRemove( d->esBufferList, esBuffer ); + if( !Push( d, audio->inFifo, &esBuffer ) ) { - d->optAudioBuf->last = 0; - if( !Push( d, d->optAudio->ac3Fifo, &d->optAudioBuf ) ) - { - return 0; - } + return 0; } - - HBListRemove( d->esBufferList, esBuffer ); - d->optAudioBuf = esBuffer; + break; } - else + + if( esBuffer ) { HBListRemove( d->esBufferList, esBuffer ); HBBufferClose( &esBuffer ); @@ -303,24 +251,16 @@ static int Demux( HBDVDRead * d ) return 1; } - + static int Push( HBDVDRead * d, HBFifo * fifo, HBBuffer ** buffer ) { - for( ;; ) + while( !d->die ) { - HBCheckPaused( d->handle ); - if( HBFifoPush( fifo, buffer ) ) { return 1; } - - if( d->die ) - { - break; - } - - HBSnooze( 10000 ); + HBSnooze( 5000 ); } return 0; diff --git a/core/DVDRead.h b/core/DVDRead.h deleted file mode 100644 index 7a9aa7e21..000000000 --- a/core/DVDRead.h +++ /dev/null @@ -1,16 +0,0 @@ -/* $Id: DVDRead.h,v 1.1 2003/11/03 12:08:00 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_DVD_READ_H -#define HB_DVD_READ_H - -#include "HandBrakeInternal.h" - -HBDVDRead * HBDVDReadInit( HBHandle *, HBTitle *, - HBAudio *, HBAudio * ); -void HBDVDReadClose( HBDVDRead ** ); - -#endif diff --git a/core/FaacEnc.c b/core/FaacEnc.c new file mode 100644 index 000000000..b55a9deb6 --- /dev/null +++ b/core/FaacEnc.c @@ -0,0 +1,214 @@ +/* $Id: FaacEnc.c,v 1.15 2004/02/18 17:07:20 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "HBInternal.h" + +/* libfaac */ +#include "faac.h" + +typedef struct HBFaacEnc +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBAudio * audio; + + faacEncHandle * faac; + unsigned long inputSamples; + unsigned long maxOutputBytes; + int32_t * inputBuffer; + unsigned long samplesGot; + HBBuffer * rawBuffer; + int rawBufferPos; /* in bytes */ + float position; + HBBuffer * aacBuffer; + + /* Stats */ + int64_t samples; + int64_t bytes; +} HBFaacEnc; + +/* Local prototypes */ +static int FaacEncWork( HBWork * ); +static int GetSamples( HBFaacEnc * ); + +HBWork * HBFaacEncInit( HBHandle * handle, HBAudio * audio ) +{ + HBFaacEnc * f; + if( !( f = calloc( sizeof( HBFaacEnc ), 1 ) ) ) + { + HBLog( "HBFaacEncInit: malloc() failed, gonna crash" ); + return NULL; + } + + f->name = strdup( "FaacEnc" ); + f->work = FaacEncWork; + + f->handle = handle; + f->audio = audio; + + return (HBWork*) f; +} + +void HBFaacEncClose( HBWork ** _f ) +{ + HBFaacEnc * f = (HBFaacEnc*) *_f; + + if( f->faac ) + { + faacEncClose( f->faac ); + free( f->inputBuffer ); + } + + if( f->samples ) + { + int64_t bytes = 128 * f->audio->outBitrate * f->samples / + f->audio->outSampleRate; + float bitrate = (float) f->bytes * f->audio->inSampleRate / + f->samples / 128; + + HBLog( "HBFaacEnc: %lld samples encoded (%lld bytes), %.2f kbps", + f->samples, f->bytes, bitrate ); + HBLog( "HBFaacEnc: error is %lld bytes", f->bytes - bytes ); + } + + free( f->name ); + free( f ); + + *_f = NULL; +} + +static int FaacEncWork( HBWork * w ) +{ + HBFaacEnc * f = (HBFaacEnc*) w; + HBAudio * audio = f->audio; + + int didSomething = 0; + + if( !f->faac ) + { + faacEncConfigurationPtr config; + + /* Get a first buffer so we know that audio->inSampleRate is + correct */ + if( ( f->rawBuffer = HBFifoPop( audio->rawFifo ) ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + f->rawBufferPos = 0; + f->position = f->rawBuffer->position; + + HBLog( "HBFaacEnc: opening libfaac (%x)", audio->id ); + + /* No resampling */ + audio->outSampleRate = audio->inSampleRate; + + f->faac = faacEncOpen( audio->outSampleRate, 2, + &f->inputSamples, &f->maxOutputBytes ); + f->inputBuffer = malloc( f->inputSamples * sizeof( int32_t ) ); + config = faacEncGetCurrentConfiguration( f->faac ); + config->mpegVersion = MPEG4; + config->aacObjectType = LOW; + config->allowMidside = 1; + config->useLfe = 0; + config->useTns = 0; + config->bitRate = audio->outBitrate * 512; + config->bandWidth = 0; + config->outputFormat = 0; + faacEncSetConfiguration( f->faac, config ); + faacEncGetDecoderSpecificInfo( f->faac, &audio->esConfig, + &audio->esConfigLength ); + } + + /* Push encoded buffer */ + if( f->aacBuffer ) + { + if( HBFifoPush( audio->outFifo, &f->aacBuffer ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + } + + if( GetSamples( f ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + f->samplesGot = 0; + + f->aacBuffer = HBBufferInit( f->maxOutputBytes ); + f->aacBuffer->position = f->position; + f->aacBuffer->size = faacEncEncode( f->faac, f->inputBuffer, + f->inputSamples, f->aacBuffer->data, f->maxOutputBytes ); + + f->samples += f->inputSamples / 2; + + if( !f->aacBuffer->size ) + { + HBBufferClose( &f->aacBuffer ); + } + else if( f->aacBuffer->size < 0 ) + { + HBLog( "HBFaacEnc: faacEncEncode() failed" ); + } + else + { + f->bytes += f->aacBuffer->size; + } + + return didSomething; +} + +static int GetSamples( HBFaacEnc * f ) +{ + while( f->samplesGot < f->inputSamples ) + { + int i, copy; + + if( !f->rawBuffer ) + { + if( !( f->rawBuffer = HBFifoPop( f->audio->rawFifo ) ) ) + { + return 0; + } + + f->rawBufferPos = 0; + f->position = f->rawBuffer->position; + } + + copy = MIN( f->inputSamples - f->samplesGot, + ( f->rawBuffer->samples - f->rawBufferPos ) * 2 ); + + for( i = 0; i < copy; i += 2 ) + { + f->inputBuffer[f->samplesGot++] = + f->rawBuffer->left[f->rawBufferPos]; + f->inputBuffer[f->samplesGot++] = + f->rawBuffer->right[f->rawBufferPos]; + f->rawBufferPos++; + } + + if( f->rawBufferPos == f->rawBuffer->samples ) + { + HBBufferClose( &f->rawBuffer ); + } + } + + return 1; +} + diff --git a/core/FfmpegEnc.c b/core/FfmpegEnc.c index 2118c29d6..4028dc5fb 100644 --- a/core/FfmpegEnc.c +++ b/core/FfmpegEnc.c @@ -1,38 +1,40 @@ -/* $Id: FfmpegEnc.c,v 1.5 2003/11/06 13:03:19 titer Exp $ +/* $Id: FfmpegEnc.c,v 1.18 2004/01/21 17:59:33 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "FfmpegEnc.h" -#include "Fifo.h" -#include "Work.h" +#include "HBInternal.h" -#include <ffmpeg/avcodec.h> +/* libavcodec */ +#include "ffmpeg/avcodec.h" -/* Extern functions */ -void HBSetPosition( HBHandle *, float ); - -/* Local prototypes */ -static int FfmpegEncWork( HBWork * ); - -struct HBFfmpegEnc +typedef struct HBFfmpegEnc { HB_WORK_COMMON_MEMBERS - HBHandle * handle; - HBTitle * title; + HBHandle * handle; + HBTitle * title; - HBBuffer * mpeg4Buffer; - int pass; + HBBuffer * mpeg4Buffer; + int pass; AVCodecContext * context; - FILE * file; -}; + FILE * file; + + /* Stats */ + int frames; + int64_t bytes; +} HBFfmpegEnc; -HBFfmpegEnc * HBFfmpegEncInit( HBHandle * handle, HBTitle * title ) +/* Local prototypes */ +static int FfmpegEncWork( HBWork * ); +static int InitAvcodec( HBFfmpegEnc * ); +static void CloseAvcodec( HBFfmpegEnc * ); + +HBWork * HBFfmpegEncInit( HBHandle * handle, HBTitle * title ) { HBFfmpegEnc * f; - if( !( f = malloc( sizeof( HBFfmpegEnc ) ) ) ) + if( !( f = calloc( sizeof( HBFfmpegEnc ), 1 ) ) ) { HBLog( "HBFfmpegEncInit: malloc() failed, gonna crash" ); return NULL; @@ -42,31 +44,32 @@ HBFfmpegEnc * HBFfmpegEncInit( HBHandle * handle, HBTitle * title ) f->work = FfmpegEncWork; f->handle = handle; - f->title = title; - - f->mpeg4Buffer = NULL; - f->pass = 42; - f->context = NULL; - f->file = NULL; + f->title = title; + f->pass = 42; - return f; + return (HBWork*) f; } -void HBFfmpegEncClose( HBFfmpegEnc ** _f ) +void HBFfmpegEncClose( HBWork ** _f ) { - HBFfmpegEnc * f = *_f; + HBFfmpegEnc * f = (HBFfmpegEnc*) *_f; if( f->context ) { - HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)", - f->pass ); + CloseAvcodec( f ); + } - avcodec_close( f->context ); - if( f->file ) - { - fclose( f->file ); - f->file = NULL; - } + /* Stats */ + if( f->frames ) + { + float bitrate = (float) f->bytes * f->title->rate / + f->frames / f->title->rateBase / 128; + int64_t bytes = (int64_t) f->frames * f->title->bitrate * 128 * + f->title->rateBase / f->title->rate; + + HBLog( "HBFfmpegEnc: %d frames encoded (%lld bytes), %.2f kbps", + f->frames, f->bytes, bitrate ); + HBLog( "HBFfmpegEnc: error is %lld bytes", f->bytes - bytes ); } free( f->name ); free( f ); @@ -87,7 +90,7 @@ static int FfmpegEncWork( HBWork * w ) if( f->mpeg4Buffer ) { - if( HBFifoPush( title->mpeg4Fifo, &f->mpeg4Buffer ) ) + if( HBFifoPush( title->outFifo, &f->mpeg4Buffer ) ) { didSomething = 1; } @@ -109,94 +112,26 @@ static int FfmpegEncWork( HBWork * w ) /* Init or re-init if needed */ if( scaledBuffer->pass != f->pass ) { - AVCodec * codec; - AVCodecContext * context; - if( f->context ) { - HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)", - f->pass ); - - avcodec_close( f->context ); - if( f->file ) - { - fclose( f->file ); - f->file = NULL; - } + CloseAvcodec( f ); } - + f->pass = scaledBuffer->pass; - - HBLog( "HBFfmpegEnc: opening libavcodec (pass %d)", f->pass ); - codec = avcodec_find_encoder( CODEC_ID_MPEG4 ); - if( !codec ) + + if( !InitAvcodec( f ) ) { - HBLog( "HBFfmpegEnc: avcodec_find_encoder() failed" ); HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT ); return didSomething; } - - context = avcodec_alloc_context(); - context->bit_rate = 1024 * title->bitrate; - context->bit_rate_tolerance = 10240 * title->bitrate; - context->width = title->outWidth; - context->height = title->outHeight; - context->frame_rate = title->rate; - context->frame_rate_base = title->rateBase; - context->gop_size = 10 * title->rate / - title->rateBase; - - if( f->pass ) - { - char fileName[1024]; memset( fileName, 0, 1024 ); - sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", - HBGetPid( f->handle ) ); - - if( f->pass == 1 ) - { - f->file = fopen( fileName, "w" ); - - context->flags |= CODEC_FLAG_PASS1; - } - else - { - FILE * file; - int size; - char * log; - - file = fopen( fileName, "r" ); - fseek( file, 0, SEEK_END ); - size = ftell( file ); - fseek( file, 0, SEEK_SET ); - if( !( log = malloc( size + 1 ) ) ) - { - HBLog( "HBFfmpegEnc: malloc() failed, gonna crash" ); - } - log[size] = '\0'; - fread( log, size, 1, file ); - fclose( file ); - - context->flags |= CODEC_FLAG_PASS2; - context->stats_in = log; - } - } - - if( avcodec_open( context, codec ) < 0 ) - { - HBLog( "HBFfmpegEnc: avcodec_open() failed" ); - HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT ); - return didSomething; - } - - f->context = context; } - frame = avcodec_alloc_frame(); - frame->data[0] = scaledBuffer->data; - frame->data[1] = frame->data[0] + title->outWidth * - title->outHeight; - frame->data[2] = frame->data[1] + title->outWidth * - title->outHeight / 4; + frame = avcodec_alloc_frame(); + frame->data[0] = scaledBuffer->data; + frame->data[1] = frame->data[0] + title->outWidth * + title->outHeight; + frame->data[2] = frame->data[1] + title->outWidth * + title->outHeight / 4; frame->linesize[0] = title->outWidth; frame->linesize[1] = title->outWidth / 2; frame->linesize[2] = title->outWidth / 2; @@ -204,9 +139,8 @@ static int FfmpegEncWork( HBWork * w ) mpeg4Buffer = HBBufferInit( 3 * title->outWidth * title->outHeight / 2 ); mpeg4Buffer->position = scaledBuffer->position; - mpeg4Buffer->size = - avcodec_encode_video( f->context, mpeg4Buffer->data, - mpeg4Buffer->alloc, frame ); + mpeg4Buffer->size = avcodec_encode_video( f->context, + mpeg4Buffer->data, mpeg4Buffer->alloc, frame ); mpeg4Buffer->keyFrame = f->context->coded_frame->key_frame; /* Inform the GUI about the current position */ @@ -220,11 +154,128 @@ static int FfmpegEncWork( HBWork * w ) } HBBufferClose( &mpeg4Buffer ); } + else + { + f->mpeg4Buffer = mpeg4Buffer; + + /* Stats */ + f->frames++; + f->bytes += mpeg4Buffer->size; + } HBBufferClose( &scaledBuffer ); free( frame ); - f->mpeg4Buffer = mpeg4Buffer; - return didSomething; } + +static int InitAvcodec( HBFfmpegEnc * f ) +{ + AVCodec * codec; + AVCodecContext * context; + HBTitle * title = f->title; + + HBLog( "HBFfmpegEnc: opening libavcodec (pass %d)", f->pass ); + + codec = avcodec_find_encoder( CODEC_ID_MPEG4 ); + if( !codec ) + { + HBLog( "HBFfmpegEnc: avcodec_find_encoder() failed" ); + HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT ); + return 0; + } + + context = avcodec_alloc_context(); + context->bit_rate = 1024 * title->bitrate; + context->bit_rate_tolerance = 10 * context->bit_rate; + context->width = title->outWidth; + context->height = title->outHeight; + context->frame_rate = title->rate; + context->frame_rate_base = title->rateBase; + context->gop_size = 10 * title->rate / title->rateBase; + + if( title->mux == HB_MUX_MP4 && f->pass != 1 ) + { + context->flags |= CODEC_FLAG_GLOBAL_HEADER; + } + + if( f->pass ) + { + char fileName[1024]; memset( fileName, 0, 1024 ); + sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", + HBGetPid( f->handle ) ); + + if( f->pass == 1 ) + { + f->file = fopen( fileName, "w" ); + context->flags |= CODEC_FLAG_PASS1; + } + else + { + FILE * file; + int size; + char * log; + + file = fopen( fileName, "r" ); + fseek( file, 0, SEEK_END ); + size = ftell( file ); + fseek( file, 0, SEEK_SET ); + if( !( log = malloc( size + 1 ) ) ) + { + HBLog( "HBFfmpegEnc: malloc() failed, gonna crash" ); + } + log[size] = '\0'; + fread( log, size, 1, file ); + fclose( file ); + + context->flags |= CODEC_FLAG_PASS2; + context->stats_in = log; + } + } + +#ifdef HB_NOMMX + context->dct_algo = FF_DCT_INT; + context->idct_algo = FF_IDCT_INT; + context->dsp_mask = 0x1F; +#endif + + if( avcodec_open( context, codec ) < 0 ) + { + HBLog( "HBFfmpegEnc: avcodec_open() failed" ); + return 0; + } + + if( title->mux == HB_MUX_MP4 && f->pass != 1 ) + { + /* UGLY */ + title->esConfig = malloc( 15 ); + title->esConfigLength = 15; + memcpy( title->esConfig, context->extradata + 15, 15 ); + } + + f->context = context; + return 1; +} + +static void CloseAvcodec( HBFfmpegEnc * f ) +{ + HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)", + f->pass ); + + if( f->context->stats_in ) + { + free( f->context->stats_in ); + } + avcodec_close( f->context ); + if( f->file ) + { + fclose( f->file ); + f->file = NULL; + } + if( f->title->esConfig ) + { + free( f->title->esConfig ); + f->title->esConfigLength = 0; + } +} + diff --git a/core/FfmpegEnc.h b/core/FfmpegEnc.h deleted file mode 100644 index 8ab622011..000000000 --- a/core/FfmpegEnc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: FfmpegEnc.h,v 1.1 2003/11/03 12:08:01 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_FFMPEG_ENC_H -#define HB_FFMPEG_ENC_H - -#include "HandBrakeInternal.h" - -HBFfmpegEnc * HBFfmpegEncInit( HBHandle *, HBTitle * ); -void HBFfmpegEncClose( HBFfmpegEnc ** ); - -#endif diff --git a/core/Fifo.c b/core/Fifo.c index 74658d5d8..af6d90cfe 100644 --- a/core/Fifo.c +++ b/core/Fifo.c @@ -1,4 +1,4 @@ -/* $Id: Fifo.c,v 1.3 2003/11/09 14:27:56 titer Exp $ +/* $Id: Fifo.c,v 1.8 2004/01/16 19:04:03 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -9,7 +9,7 @@ HBBuffer * HBBufferInit( int size ) { HBBuffer * b; - if( !( b = malloc( sizeof( HBBuffer ) ) ) ) + if( !( b = calloc( sizeof( HBBuffer ), 1 ) ) ) { HBLog( "HBBufferInit: malloc() failed, gonna crash" ); return NULL; @@ -26,11 +26,6 @@ HBBuffer * HBBufferInit( int size ) } b->position = 0.0; - b->streamId = 0; - b->keyFrame = 0; - b->pts = 0; - b->pass = 0; - b->last = 0; return b; } @@ -49,7 +44,7 @@ void HBBufferReAlloc( HBBuffer * b, int size ) void HBBufferClose( HBBuffer ** _b ) { HBBuffer * b = *_b; - + free( b->data ); free( b ); @@ -65,6 +60,7 @@ HBFifo * HBFifoInit( int capacity ) return NULL; } + f->die = 0; f->capacity = capacity; f->whereToPush = 0; f->whereToPop = 0; @@ -75,22 +71,23 @@ HBFifo * HBFifoInit( int capacity ) free( f ); return NULL; } - + f->lock = HBLockInit(); + f->cond = HBCondInit(); return f; } -int HBFifoSize( HBFifo * f ) +void HBFifoDie( HBFifo * f ) { - return ( f->capacity + 1 + f->whereToPush - f->whereToPop ) % - ( f->capacity + 1 ); + f->die = 1; + HBCondSignal( f->cond ); } void HBFifoClose( HBFifo ** _f ) { HBFifo * f = (*_f); - + HBLog( "HBFifoClose: trashing %d buffer%s", HBFifoSize( f ), ( HBFifoSize( f ) > 1 ) ? "s" : "" ); @@ -102,6 +99,7 @@ void HBFifoClose( HBFifo ** _f ) } HBLockClose( &f->lock ); + HBCondClose( &f->cond ); free( f->buffers ); free( f ); diff --git a/core/Fifo.h b/core/Fifo.h index 758125ebd..d9240fb25 100644 --- a/core/Fifo.h +++ b/core/Fifo.h @@ -1,4 +1,4 @@ -/* $Id: Fifo.h,v 1.3 2003/11/06 13:07:52 titer Exp $ +/* $Id: Fifo.h,v 1.10 2004/01/16 19:04:04 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -12,16 +12,27 @@ struct HBBuffer { + /* Members used everywhere */ int alloc; int size; uint8_t * data; - float position; + int pass; + + /* Only used for PStoES */ int streamId; - int keyFrame; uint64_t pts; - int pass; - int last; + + /* NTSC suxx */ + int repeat; + + /* Only used for raw audio buffers */ + int samples; /* Number of samples for each track */ + float * left; + float * right; + + /* Only used for MPEG-4, MP3 and AAC buffers */ + int keyFrame; }; HBBuffer * HBBufferInit( int size ); @@ -30,24 +41,40 @@ void HBBufferClose( HBBuffer ** ); struct HBFifo { + int die; int capacity; int whereToPush; int whereToPop; HBBuffer ** buffers; HBLock * lock; + HBCond * cond; }; HBFifo * HBFifoInit( int capacity ); -int HBFifoSize( HBFifo * ); +static inline int HBFifoSize( HBFifo * ); static inline int HBFifoPush( HBFifo *, HBBuffer ** ); static inline HBBuffer * HBFifoPop( HBFifo * ); +static inline int HBFifoWait( HBFifo * ); +static inline float HBFifoPosition( HBFifo * ); +void HBFifoDie( HBFifo * ); void HBFifoClose( HBFifo ** ); -static inline int HBFifoPush( HBFifo * f, HBBuffer ** b ) +static inline int HBFifoSize( HBFifo * f ) { + int size; HBLockLock( f->lock ); + size = ( f->capacity + 1 + f->whereToPush - f->whereToPop ) % + ( f->capacity + 1 ); + HBLockUnlock( f->lock ); + return size; +} - if( HBFifoSize( f ) < f->capacity ) +static inline int HBFifoPush( HBFifo * f, HBBuffer ** b ) +{ + HBLockLock( f->lock ); + HBCondSignal( f->cond ); + if( ( f->capacity + 1 + f->whereToPush - f->whereToPop ) % + ( f->capacity + 1 ) != f->capacity ) { f->buffers[f->whereToPush] = *b; f->whereToPush++; @@ -56,7 +83,6 @@ static inline int HBFifoPush( HBFifo * f, HBBuffer ** b ) *b = NULL; return 1; } - HBLockUnlock( f->lock ); return 0; } @@ -64,7 +90,6 @@ static inline int HBFifoPush( HBFifo * f, HBBuffer ** b ) static inline HBBuffer * HBFifoPop( HBFifo * f ) { HBLockLock( f->lock ); - if( f->whereToPush != f->whereToPop ) { HBBuffer * b = f->buffers[f->whereToPop]; @@ -73,9 +98,47 @@ static inline HBBuffer * HBFifoPop( HBFifo * f ) HBLockUnlock( f->lock ); return b; } - HBLockUnlock( f->lock ); return NULL; } +static inline int HBFifoWait( HBFifo * f ) +{ + HBLockLock( f->lock ); + if( f->whereToPush != f->whereToPop ) + { + HBLockUnlock( f->lock ); + return 1; + } + if( f->die ) + { + HBLockUnlock( f->lock ); + return 0; + } + HBCondWait( f->cond, f->lock ); + if( f->whereToPush != f->whereToPop ) + { + HBLockUnlock( f->lock ); + return 1; + } + HBLockUnlock( f->lock ); + return 0; +} + +static inline float HBFifoPosition( HBFifo * f ) +{ + float pos; + HBLockLock( f->lock ); + if( f->whereToPush != f->whereToPop ) + { + pos = f->buffers[f->whereToPop]->position; + } + else + { + pos = 0.0; + } + HBLockUnlock( f->lock ); + return pos; +} + #endif diff --git a/core/HBInternal.h b/core/HBInternal.h new file mode 100644 index 000000000..169451980 --- /dev/null +++ b/core/HBInternal.h @@ -0,0 +1,81 @@ +/* $Id: HBInternal.h,v 1.4 2004/01/16 20:55:21 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_INTERNAL_H +#define HB_INTERNAL_H + +#include "HandBrake.h" +#include "Fifo.h" +#include "Thread.h" +#include "Work.h" + +/* Demuxer */ +HBDVDRead * HBDVDReadInit( HBHandle *, HBTitle * ); +void HBDVDReadClose( HBDVDRead ** ); + +/* Decoders */ +HBWork * HBMpeg2DecInit( HBHandle *, HBTitle * ); +void HBMpeg2DecClose( HBWork ** ); +HBWork * HBAc3DecInit( HBHandle *, HBAudio * ); +void HBAc3DecClose( HBWork ** ); +HBWork * HBMadDecInit( HBHandle *, HBAudio * ); +void HBMadDecClose( HBWork ** ); + +/* Scaler */ +HBWork * HBScaleInit( HBHandle *, HBTitle * ); +void HBScaleClose( HBWork ** ); + +/* Encoders */ +HBWork * HBFfmpegEncInit( HBHandle *, HBTitle * ); +void HBFfmpegEncClose( HBWork ** ); +HBWork * HBXvidEncInit( HBHandle *, HBTitle * ); +void HBXvidEncClose( HBWork ** ); +HBWork * HBX264EncInit( HBHandle *, HBTitle * ); +void HBX264EncClose( HBWork ** ); +HBWork * HBMp3EncInit( HBHandle *, HBAudio * ); +void HBMp3EncClose( HBWork ** ); +HBWork * HBFaacEncInit( HBHandle *, HBAudio * ); +void HBFaacEncClose( HBWork ** ); +HBWork * HBVorbisEncInit ( HBHandle *, HBAudio * ); +void HBVorbisEncClose( HBWork ** ); + +/* Muxers */ +HBAviMux * HBAviMuxInit( HBHandle *, HBTitle * ); +void HBAviMuxClose( HBAviMux ** ); +HBMp4Mux * HBMp4MuxInit( HBHandle *, HBTitle * ); +void HBMp4MuxClose( HBMp4Mux ** ); +HBOgmMux * HBOgmMuxInit( HBHandle *, HBTitle * ); +void HBOgmMuxClose( HBOgmMux ** ); + +/* Scanner */ +HBScan * HBScanInit( HBHandle *, const char * device, int title ); +void HBScanClose( HBScan ** ); + +/* Called by HBScan to tell the GUI how far we've been */ +void HBScanning( HBHandle *, int title, int titleCount ); + +/* Called by HBScan. titleList is a list of all valid titles which + should be shown on the interface */ +void HBScanDone( HBHandle *, HBList * titleList ); + +/* Used to create temporary files (/tmp/HB.pid.whatever) */ +int HBGetPid( HBHandle * ); + +/* Called by every thread involved in the rip process. Returns + immediately is rip isn't paused, blocks until the rip is resumed + otherwise */ +void HBCheckPaused( HBHandle * ); + +/* Called by the decoders when the last packet is being proceeded */ +void HBDone( HBHandle * ); + +/* Called by the video encoder to update the GUI progress */ +void HBPosition( HBHandle *, float ); + +/* Called by any thread which couldn't continue and asks to stop */ +void HBErrorOccured( HBHandle *, int error ); + +#endif diff --git a/core/HandBrake.c b/core/HandBrake.c index c76a27b3c..010f1a3cf 100644 --- a/core/HandBrake.c +++ b/core/HandBrake.c @@ -1,25 +1,13 @@ -/* $Id: HandBrake.c,v 1.18 2003/11/13 01:17:33 titer Exp $ +/* $Id: HandBrake.c,v 1.42 2004/02/18 17:07:20 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "HandBrakeInternal.h" +#include "HBInternal.h" -#include <ffmpeg/avcodec.h> - -#include "Ac3Dec.h" -#include "AviMux.h" -#include "DVDRead.h" -#include "FfmpegEnc.h" -#include "Fifo.h" -#include "Mp3Enc.h" -#include "Mpeg2Dec.h" -#include "Scale.h" -#include "Scan.h" -#include "Thread.h" -#include "Work.h" -#include "XvidEnc.h" +/* libavcodec */ +#include "ffmpeg/avcodec.h" /* Local prototypes */ static void HandBrakeThread( void * ); @@ -29,39 +17,37 @@ static int GetCPUCount(); struct HBHandle { - HBThread * thread; - int die; - int pid; - - int cpuCount; - - int stopScan; - int stopRip; - int ripDone; - int error; - - HBScan * scan; - - HBLock * lock; - HBStatus status; - int modeChanged; - HBTitle * curTitle; - HBAudio * curAudio; - HBAudio * curOptAudio; - - int frames; - uint64_t beginDate; - int framesSinceFpsUpdate; - uint64_t lastFpsUpdate; - uint64_t pauseDate; - - HBLock * pauseLock; + int cpuCount; + HBCallbacks cb; + + int stopScan; + int stopRip; + int ripDone; + int error; + + HBScan * scan; + HBList * titleList; + HBTitle * curTitle; + uint64_t beginDate; + uint64_t pauseDate; + uint64_t lastPosUpdate; + uint64_t lastFpsUpdate; + int framesSinceBegin; + int framesSinceFps; + float curFrameRate; + float avgFrameRate; + int remainingTime; + + HBLock * pauseLock; + volatile int die; + HBThread * thread; + int pid; }; HBHandle * HBInit( int debug, int cpuCount ) { HBHandle * h; - if( !( h = malloc( sizeof( HBHandle ) ) ) ) + if( !( h = calloc( sizeof( HBHandle ), 1 ) ) ) { HBLog( "HBInit: malloc() failed, gonna crash" ); return NULL; @@ -105,190 +91,105 @@ HBHandle * HBInit( int debug, int cpuCount ) h->cpuCount = cpuCount; } } - - /* Initializations */ - h->stopScan = 0; - h->stopRip = 0; - h->ripDone = 0; - h->error = 0; - - h->scan = NULL; - - h->lock = HBLockInit(); - h->modeChanged = 1; - h->status.mode = HB_MODE_NEED_DEVICE; - h->status.titleList = NULL; - h->curTitle = NULL; - h->curAudio = NULL; - h->curOptAudio = NULL; h->pauseLock = HBLockInit(); - - h->die = 0; - h->thread = HBThreadInit( "libhb", HandBrakeThread, h, - HB_NORMAL_PRIORITY ); - + h->thread = HBThreadInit( "libhb", HandBrakeThread, h, + HB_NORMAL_PRIORITY ); return h; } -int HBGetStatus( HBHandle * h, HBStatus * status ) +void HBSetCallbacks( HBHandle * h, HBCallbacks callbacks ) { - HBLockLock( h->lock ); - memcpy( status, &h->status, sizeof( HBStatus ) ); - - if( !h->modeChanged ) - { - HBLockUnlock( h->lock ); - return 0; - } - - h->modeChanged = 0; - HBLockUnlock( h->lock ); - return 1; + h->cb = callbacks; } -void HBScanDevice( HBHandle * h, char * device, int title ) +void HBScanDVD( HBHandle * h, const char * dvd, int title ) { - if( !( h->status.mode & ( HB_MODE_NEED_DEVICE | - HB_MODE_INVALID_DEVICE ) ) ) - { - HBLog( "HBScanDevice: current mode is %d, aborting", - h->status.mode ); - return; - } - - HBLockLock( h->lock ); - h->modeChanged = 1; - h->status.mode = HB_MODE_SCANNING; - h->status.scannedTitle = 0; - HBLockUnlock( h->lock ); - - h->scan = HBScanInit( h, device, title ); + h->scan = HBScanInit( h, dvd, title ); } -void HBStartRip( HBHandle * h, HBTitle * t, - HBAudio * a1, HBAudio * a2 ) +void HBStartRip( HBHandle * h, HBTitle * title ) { int i; - - if( !( h->status.mode & ( HB_MODE_READY_TO_RIP | HB_MODE_DONE | - HB_MODE_CANCELED | HB_MODE_ERROR ) ) ) - { - HBLog( "HBStartRip: current mode is %d, aborting", - h->status.mode ); - return; + HBAudio * audio; + + h->beginDate = HBGetDate(); + h->lastPosUpdate = 0; + h->lastFpsUpdate = 0; + h->framesSinceBegin = 0; + h->framesSinceFps = 0; + + FixPictureSettings( title ); + + /* Video fifos */ + title->inFifo = HBFifoInit( 1024 ); + title->rawFifo = HBFifoInit( 1 ); + title->scaledFifo = HBFifoInit( 1 ); + title->outFifo = HBFifoInit( 1 ); + + /* Video work objects */ + title->decoder = HBMpeg2DecInit( h, title ); + title->scale = HBScaleInit( h, title ); + if( title->codec == HB_CODEC_FFMPEG ) + title->encoder = HBFfmpegEncInit( h, title ); + else if( title->codec == HB_CODEC_XVID ) + title->encoder = HBXvidEncInit( h, title ); + else if( title->codec == HB_CODEC_X264 ) + title->encoder = HBX264EncInit( h, title ); + + for( i = 0; i < HBListCount( title->ripAudioList ); i++ ) + { + audio = HBListItemAt( title->ripAudioList, i ); + + /* Audio fifos */ + audio->inFifo = HBFifoInit( 1024 ); + audio->rawFifo = HBFifoInit( 1 ); + audio->outFifo = HBFifoInit( 4 ); /* At least 4 for Vorbis */ + + /* Audio work objects */ + audio->decoder = HBAc3DecInit( h, audio ); + if( audio->codec == HB_CODEC_MP3 ) + audio->encoder = HBMp3EncInit( h, audio ); + else if( audio->codec == HB_CODEC_AAC ) + audio->encoder = HBFaacEncInit( h, audio ); + else if( audio->codec == HB_CODEC_VORBIS ) + audio->encoder = HBVorbisEncInit( h, audio ); } - HBLockLock( h->lock ); - h->modeChanged = 1; - h->status.mode = HB_MODE_ENCODING; - h->status.position = 0.0; - h->status.pass = 1; - h->status.passCount = t->twoPass ? 2 : 1; - h->frames = 0; - h->framesSinceFpsUpdate = 0; - HBLockUnlock( h->lock ); - - FixPictureSettings( t ); + /* Create threads */ + title->dvdRead = HBDVDReadInit( h, title ); - /* Create fifos */ - t->mpeg2Fifo = HBFifoInit( 1024 ); - t->rawFifo = HBFifoInit( 1 ); - t->scaledFifo = HBFifoInit( 1 ); - t->mpeg4Fifo = HBFifoInit( 1 ); - a1->ac3Fifo = HBFifoInit( 1024 ); - a1->rawFifo = HBFifoInit( 1 ); - a1->mp3Fifo = HBFifoInit( 1 ); - if( a2 ) - { - a2->ac3Fifo = HBFifoInit( 1024 ); - a2->rawFifo = HBFifoInit( 1 ); - a2->mp3Fifo = HBFifoInit( 1 ); - } + if( title->mux == HB_MUX_AVI ) + title->aviMux = HBAviMuxInit( h, title ); + else if( title->mux == HB_MUX_MP4 ) + title->mp4Mux = HBMp4MuxInit( h, title ); + else if( title->mux == HB_MUX_OGM ) + title->ogmMux = HBOgmMuxInit( h, title ); - /* Create work objects */ - t->mpeg2Dec = HBMpeg2DecInit( h, t ); - t->scale = HBScaleInit( h, t ); - - if( t->codec == HB_CODEC_FFMPEG ) - t->ffmpegEnc = HBFfmpegEncInit( h, t ); - else if( t->codec == HB_CODEC_XVID ) - t->xvidEnc = HBXvidEncInit( h, t ); - - a1->ac3Dec = HBAc3DecInit( h, a1 ); - a1->mp3Enc = HBMp3EncInit( h, a1 ); - if( a2 ) - { - a2->ac3Dec = HBAc3DecInit( h, a2 ); - a2->mp3Enc = HBMp3EncInit( h, a2 ); - } - - /* Create threads */ - t->dvdRead = HBDVDReadInit( h, t, a1, a2 ); - t->aviMux = HBAviMuxInit( h, t, a1, a2 ); for( i = 0; i < h->cpuCount; i++ ) { - t->workThreads[i] = HBWorkThreadInit( h, t, a1, a2, i ? 0 : 1 ); + title->workThreads[i] = HBWorkThreadInit( h, title, i ? 0 : 1 ); } - h->curTitle = t; - h->curAudio = a1; - h->curOptAudio = a2; + h->curTitle = title; } void HBPauseRip( HBHandle * h ) { - if( h->status.mode != HB_MODE_ENCODING ) - { - HBLog( "HBPauseRip: current mode is %d, aborting", - h->status.mode ); - return; - } - h->pauseDate = HBGetDate(); HBLockLock( h->pauseLock ); - HBLockLock( h->lock ); - h->status.mode = HB_MODE_PAUSED; - h->modeChanged = 1; - HBLockUnlock( h->lock ); } void HBResumeRip( HBHandle * h ) { - if( h->status.mode != HB_MODE_PAUSED ) - { - HBLog( "HBResumeRip: current mode is %d, aborting", - h->status.mode ); - return; - } - h->beginDate += HBGetDate() - h->pauseDate; + h->lastPosUpdate += HBGetDate() - h->pauseDate; h->lastFpsUpdate += HBGetDate() - h->pauseDate; HBLockUnlock( h->pauseLock ); - HBLockLock( h->lock ); - h->modeChanged = 1; - h->status.mode = HB_MODE_ENCODING; - HBLockUnlock( h->lock ); } void HBStopRip( HBHandle * h ) { - if( !( h->status.mode & ( HB_MODE_ENCODING | HB_MODE_PAUSED ) ) ) - { - HBLog( "HBStopRip: current mode is %d, aborting", - h->status.mode ); - return; - } - - if( h->status.mode & HB_MODE_PAUSED ) - { - HBLockUnlock( h->pauseLock ); - } - - HBLockLock( h->lock ); - h->modeChanged = 1; - h->status.mode = HB_MODE_STOPPING; - HBLockUnlock( h->lock ); h->stopRip = 1; } @@ -314,7 +215,7 @@ uint8_t * HBGetPreview( HBHandle * h, HBTitle * t, int picture ) HBLog( "HBGetPreview: malloc() failed, gonna crash" ); return NULL; } - + /* Original YUV picture */ avpicture_fill( &pic1, buf1, PIX_FMT_YUV420P, t->inWidth, t->inHeight ); @@ -393,7 +294,7 @@ uint8_t * HBGetPreview( HBHandle * h, HBTitle * t, int picture ) for( i = 0; i < t->outHeight; i++ ) { uint8_t * nextLine = pen + 4 * ( t->outWidthMax + 2 ); - + memset( pen, 0xFF, 4 ); pen += 4; memcpy( pen, buf4 + 4 * t->outWidth * i, 4 * t->outWidth ); @@ -415,48 +316,90 @@ uint8_t * HBGetPreview( HBHandle * h, HBTitle * t, int picture ) return NULL; } +int HBGetBitrateForSize( HBTitle * title, int size, int muxer, + int audioCount, int audioBitrate ) +{ + int64_t available; + int overheadPerFrame; + int sampleRate; + int samplesPerFrame; + + switch( muxer ) + { + case HB_MUX_MP4: + overheadPerFrame = 5; /* hopefully */ + sampleRate = 48000; /* No resampling */ + samplesPerFrame = 1024; /* AAC */ + break; + case HB_MUX_AVI: + overheadPerFrame = 24; + sampleRate = 44100; /* Resampling */ + samplesPerFrame = 1152; /* MP3 */ + break; + case HB_MUX_OGM: + overheadPerFrame = 0; /* XXX */ + sampleRate = 48000; /* No resampling */ + samplesPerFrame = 1024; /* Vorbis */ + break; + default: + return 0; + } + + /* Actually target 1 MB less */ + available = (int64_t) ( size - 1 ) * 1024 * 1024; + + /* Audio data */ + available -= audioCount * title->length * audioBitrate * 128; + + /* Video headers */ + available -= (int64_t) title->length * title->rate * + overheadPerFrame / title->rateBase; + + /* Audio headers */ + available -= (int64_t) audioCount * title->length * sampleRate * + overheadPerFrame / samplesPerFrame; + + if( available < 0 ) + { + return 0; + } + return( available / ( 128 * title->length ) ); +} + void HBClose( HBHandle ** _h ) { char command[1024]; - + HBHandle * h = *_h; - + h->die = 1; HBThreadClose( &h->thread ); - if( h->status.mode == HB_MODE_SCANNING ) + if( h->scan ) { HBScanClose( &h->scan ); } - else if( h->status.mode == HB_MODE_PAUSED ) + if( h->curTitle ) { - HBLockUnlock( h->pauseLock ); _StopRip( h ); } - else if( h->status.mode == HB_MODE_ENCODING ) + if( h->titleList ) { - _StopRip( h ); + HBTitle * title; + while( ( title = (HBTitle*) HBListItemAt( h->titleList, 0 ) ) ) + { + HBListRemove( h->titleList, title ); + HBTitleClose( &title ); + } } memset( command, 0, 1024 ); sprintf( command, "rm -f /tmp/HB.%d.*", h->pid ); system( command ); - if( h->status.titleList ) - { - HBTitle * title; - while( ( title = HBListItemAt( h->status.titleList, 0 ) ) ) - { - HBListRemove( h->status.titleList, title ); - HBTitleClose( &title ); - } - HBListClose( &h->status.titleList ); - } - - HBLockClose( &h->lock ); HBLockClose( &h->pauseLock ); free( h ); - + *_h = NULL; } @@ -467,17 +410,16 @@ void HBCheckPaused( HBHandle * h ) HBLockUnlock( h->pauseLock ); } -void HBScanning( HBHandle * h, int title ) +void HBScanning( HBHandle * h, int title, int titleCount ) { - HBLockLock( h->lock ); - h->status.scannedTitle = title; - HBLockUnlock( h->lock ); + h->cb.scanning( h->cb.data, title, titleCount ); } void HBScanDone( HBHandle * h, HBList * titleList ) { - h->status.titleList = titleList; - h->stopScan = 1; + h->stopScan = 1; + h->titleList = titleList; + h->cb.scanDone( h->cb.data, titleList ); } int HBGetPid( HBHandle * h ) @@ -492,59 +434,47 @@ void HBDone( HBHandle * h ) void HBPosition( HBHandle * h, float position ) { - if( !h->frames ) - { - h->beginDate = HBGetDate(); - h->lastFpsUpdate = h->beginDate; - } - - h->frames++; - h->framesSinceFpsUpdate++; - - HBLockLock( h->lock ); - h->status.position = position; + int pass, passCount; + + h->framesSinceBegin++; + h->framesSinceFps++; + if( h->curTitle->twoPass ) { - h->status.pass = ( position < 0.5 ) ? 1 : 2; + pass = ( position < 0.5 ) ? 1 : 2; + passCount = 2; } else { - h->status.pass = 1; + passCount = pass = 1; } + if( HBGetDate() - h->lastPosUpdate < 200000 ) + return; + + h->lastPosUpdate = HBGetDate(); + if( HBGetDate() - h->lastFpsUpdate > 1000000 ) { - h->status.frameRate = 1000000.0 * h->framesSinceFpsUpdate / - ( HBGetDate() - h->lastFpsUpdate ); - h->status.avFrameRate = 1000000.0 * h->frames / - ( HBGetDate() - h->beginDate ); - h->status.remainingTime = ( 1.0 - h->status.position ) * - ( HBGetDate() - h->beginDate ) / - h->status.position / 1000000; - - HBLog( "Progress: %.2f %%", position * 100 ); - HBLog( "Speed: %.2f fps (average: %.2f fps, " - "remaining: %02d:%02d:%02d)", - h->status.frameRate, h->status.avFrameRate, - h->status.remainingTime / 3600, - ( h->status.remainingTime / 60 ) % 60, - h->status.remainingTime % 60 ); - - h->lastFpsUpdate = HBGetDate(); - h->framesSinceFpsUpdate = 0; + h->curFrameRate = 1000000.0 * h->framesSinceFps / + ( HBGetDate() - h->lastFpsUpdate ); + h->avgFrameRate = 1000000.0 * h->framesSinceBegin / + ( HBGetDate() - h->beginDate ); + h->remainingTime = ( 1.0 - position ) * + ( HBGetDate() - h->beginDate ) / position / 1000000; + + h->lastFpsUpdate = HBGetDate(); + h->framesSinceFps = 0; } - HBLockUnlock( h->lock ); + + h->cb.encoding( h->cb.data, position, pass, passCount, + h->curFrameRate, h->avgFrameRate, + h->remainingTime ); } -void HBErrorOccured( HBHandle * h, HBError error ) +void HBErrorOccured( HBHandle * h, int error ) { - if( !( h->status.mode & ( HB_MODE_ENCODING | HB_MODE_PAUSED ) ) ) - { - return; - } - - h->status.error = error; - h->error = 1; + h->error = error; } /* Local functions */ @@ -559,49 +489,55 @@ static void HandBrakeThread( void * _h ) if( h->stopScan ) { HBScanClose( &h->scan ); - HBLockLock( h->lock ); - h->modeChanged = 1; - h->status.mode = HBListCountItems( h->status.titleList ) ? - HB_MODE_READY_TO_RIP : HB_MODE_INVALID_DEVICE; - HBLockUnlock( h->lock ); h->stopScan = 0; } if( h->stopRip ) { _StopRip( h ); - - HBLockLock( h->lock ); - h->modeChanged = 1; - h->status.mode = HB_MODE_CANCELED; - HBLockUnlock( h->lock ); - + h->cb.ripDone( h->cb.data, HB_CANCELED ); h->stopRip = 0; } if( h->ripDone ) { - /* Wait a bit */ - HBSnooze( 500000 ); + HBTitle * title = h->curTitle; + HBAudio * audio; + int i, ok = 0; + + /* Wait until we're done with the decoding of one track */ + for( ;; ) + { + if( !HBFifoSize( title->inFifo ) && + !HBFifoSize( title->rawFifo ) && + !HBFifoSize( title->scaledFifo ) ) + { + break; + } + for( i = 0; i < HBListCount( title->ripAudioList ); i++ ) + { + audio = (HBAudio*) HBListItemAt( title->ripAudioList, i ); + if( !HBFifoSize( title->inFifo ) && + !HBFifoSize( title->rawFifo ) ) + { + ok = 1; + break; + } + } + HBSnooze( 5000 ); + } + HBSnooze( 500000 ); _StopRip( h ); - HBLockLock( h->lock ); - h->modeChanged = 1; - h->status.mode = HB_MODE_DONE; - HBLockUnlock( h->lock ); - + h->cb.ripDone( h->cb.data, HB_SUCCESS ); + h->ripDone = 0; } if( h->error ) { _StopRip( h ); - - HBLockLock( h->lock ); - h->modeChanged = 1; - h->status.mode = HB_MODE_ERROR; - HBLockUnlock( h->lock ); - + h->cb.ripDone( h->cb.data, h->error ); h->error = 0; } @@ -611,52 +547,77 @@ static void HandBrakeThread( void * _h ) static void _StopRip( HBHandle * h ) { + HBTitle * title = h->curTitle; + HBAudio * audio; int i; + /* Invalidate fifos */ + HBFifoDie( title->outFifo ); + for( i = 0; i < HBListCount( title->ripAudioList ); i++ ) + { + audio = HBListItemAt( title->ripAudioList, i ); + HBFifoDie( audio->outFifo ); + } + /* Stop threads */ - HBDVDReadClose( &h->curTitle->dvdRead ); - HBAviMuxClose( &h->curTitle->aviMux ); + HBDVDReadClose( &title->dvdRead ); + + if( title->mux == HB_MUX_AVI ) + HBAviMuxClose( &title->aviMux ); + else if( title->mux == HB_MUX_MP4 ) + HBMp4MuxClose( &title->mp4Mux ); + else if( title->mux == HB_MUX_OGM ) + HBOgmMuxClose( &title->ogmMux ); + for( i = 0; i < h->cpuCount; i++ ) { - HBWorkThreadClose( &h->curTitle->workThreads[h->cpuCount-i-1] ); + HBWorkThreadClose( &title->workThreads[h->cpuCount-i-1] ); } /* Clean up */ - HBMpeg2DecClose( &h->curTitle->mpeg2Dec ); - HBScaleClose( &h->curTitle->scale ); - - if( h->curTitle->codec == HB_CODEC_FFMPEG ) - HBFfmpegEncClose( &h->curTitle->ffmpegEnc ); - else if( h->curTitle->codec == HB_CODEC_XVID ) - HBXvidEncClose( &h->curTitle->xvidEnc ); - - HBAc3DecClose( &h->curAudio->ac3Dec ); - HBMp3EncClose( &h->curAudio->mp3Enc ); - if( h->curOptAudio ) - { - HBAc3DecClose( &h->curOptAudio->ac3Dec ); - HBMp3EncClose( &h->curOptAudio->mp3Enc ); - } + HBMpeg2DecClose( &title->decoder ); + HBScaleClose( &title->scale ); - /* Destroy fifos */ - HBFifoClose( &h->curTitle->mpeg2Fifo ); - HBFifoClose( &h->curTitle->rawFifo ); - HBFifoClose( &h->curTitle->scaledFifo ); - HBFifoClose( &h->curTitle->mpeg4Fifo ); - HBFifoClose( &h->curAudio->ac3Fifo ); - HBFifoClose( &h->curAudio->rawFifo ); - HBFifoClose( &h->curAudio->mp3Fifo ); - if( h->curOptAudio ) + if( title->codec == HB_CODEC_FFMPEG ) + HBFfmpegEncClose( &title->encoder ); + else if( title->codec == HB_CODEC_XVID ) + HBXvidEncClose( &title->encoder ); + else if( title->codec == HB_CODEC_X264 ) + HBX264EncClose( &title->encoder ); + + HBFifoClose( &title->inFifo ); + HBFifoClose( &title->rawFifo ); + HBFifoClose( &title->scaledFifo ); + HBFifoClose( &title->outFifo ); + + for( i = 0; i < HBListCount( title->ripAudioList ); i++ ) { - HBFifoClose( &h->curOptAudio->ac3Fifo ); - HBFifoClose( &h->curOptAudio->rawFifo ); - HBFifoClose( &h->curOptAudio->mp3Fifo ); + audio = HBListItemAt( title->ripAudioList, i ); + + /* Audio work objects */ + HBAc3DecClose( &audio->decoder ); + if( audio->codec == HB_CODEC_MP3 ) + HBMp3EncClose( &audio->encoder ); + else if( audio->codec == HB_CODEC_AAC ) + HBFaacEncClose( &audio->encoder ); + else if( audio->codec == HB_CODEC_VORBIS ) + HBVorbisEncClose( &audio->encoder ); + + /* Audio fifos */ + HBFifoClose( &audio->inFifo ); + HBFifoClose( &audio->rawFifo ); + HBFifoClose( &audio->outFifo ); + + HBListRemove( title->ripAudioList, audio ); } + + h->curTitle = NULL; } static void FixPictureSettings( HBTitle * t ) { /* Sanity checks */ + t->outWidth = MULTIPLE_16( t->outWidth ); t->topCrop = EVEN( t->topCrop ); t->bottomCrop = EVEN( t->bottomCrop ); t->leftCrop = EVEN( t->leftCrop ); @@ -693,12 +654,12 @@ static int GetCPUCount() { int CPUCount = 1; -#if defined( SYS_BEOS ) +#if defined( HB_BEOS ) system_info info; get_system_info( &info ); CPUCount = info.cpu_count; -#elif defined( SYS_MACOSX ) +#elif defined( HB_MACOSX ) FILE * info; char buffer[256]; @@ -726,8 +687,8 @@ static int GetCPUCount() { HBLog( "GetCPUCount: popen() failed" ); } - -#elif defined( SYS_LINUX ) + +#elif defined( HB_LINUX ) FILE * info; char buffer[256]; @@ -755,11 +716,11 @@ static int GetCPUCount() { HBLog( "GetCPUCount: fopen() failed" ); } - -#elif defined( SYS_CYGWIN ) + +#elif defined( HB_CYGWIN ) /* TODO */ CPUCount = 1; - + #endif CPUCount = MAX( 1, CPUCount ); CPUCount = MIN( CPUCount, 8 ); diff --git a/core/HandBrake.h b/core/HandBrake.h index 35ec0fc0a..9d84d39dc 100644 --- a/core/HandBrake.h +++ b/core/HandBrake.h @@ -1,4 +1,4 @@ -/* $Id: HandBrake.h,v 1.3 2003/11/06 13:03:19 titer Exp $ +/* $Id: HandBrake.h,v 1.10 2004/01/21 18:40:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -13,36 +13,56 @@ extern "C" { #include "Utils.h" +/* Interface callbacks */ +typedef struct HBCallbacks +{ + void * data; + + void (*scanning) ( void * data, int title, int titleCount ); + void (*scanDone) ( void * data, HBList * titleList ); + void (*encoding) ( void * data, float position, int pass, + int passCount, float curFrameRate, + float avgFrameRate, int remainingTime ); + void (*ripDone) ( void * data, int result ); + +} HBCallbacks; + /* Init libhb. Set debug to 0 to see no output, 1 to see all libhb logs. Set cpuCount to 0 if you want libhb to autodetect */ HBHandle * HBInit( int debug, int cpuCount ); -/* Fills the HBStatus * argument with infos about the current status. - Returns 1 if mode has changed, 0 otherwise */ -int HBGetStatus( HBHandle *, HBStatus * ); +/* Tell libhb what functions should be called when a GUI should be + updated. */ +void HBSetCallbacks( HBHandle *, HBCallbacks callbacks ); -/* Launch a thread which scans the specified device and title. Use +/* Launch a thread which scans the specified DVD and title. Use title = 0 to scan all titles. Returns immediately */ -void HBScanDevice( HBHandle *, char * device, int title ); +void HBScanDVD( HBHandle *, const char * dvd, int title ); + +/* Calculate bitrate so the output file fits in X MB */ +int HBGetBitrateForSize( HBTitle * title, int size, int muxer, + int audioCount, int audioBitrate ); -/* Start ripping the specified title with specified audio tracks. - Returns immediatly */ -void HBStartRip( HBHandle *, HBTitle *, HBAudio *, HBAudio * ); +/* Start ripping the specified title. Returns immediatly */ +void HBStartRip( HBHandle *, HBTitle * ); -/* Suspend rip. Returns immediatly */ +/* Suspend rip */ void HBPauseRip( HBHandle * ); -/* Resume rip. Returns immediatly */ +/* Resume rip */ void HBResumeRip( HBHandle * ); -/* Cancel rip. Returns immediatly */ +/* Cancel rip. Returns immediatly - you'll be noticed by the ripDone + callback when it's really stopped. + If the rip was paused, you _must_ call HBResumeRip() first. */ void HBStopRip( HBHandle * ); /* Calculate preview for the specified picture of the specified title, taking care of the current cropping & scaling settings. Returns a - pointer to raw RGBA data. It includes the white border around the - picture, so the size of the picture is ( maxWidth + 2 ) x - ( maxHeight + 2 ) */ + pointer to raw RGBA data that _has_ to be freed by the calling + function. The picture includes the white border around the picture, + so its size is ( maxWidth + 2 ) x ( maxHeight + 2 ). + The data belongs to the caller, who must free it. */ uint8_t * HBGetPreview( HBHandle *, HBTitle *, int picture ); /* Clean up things */ diff --git a/core/HandBrakeInternal.h b/core/HandBrakeInternal.h deleted file mode 100644 index 7c10512c9..000000000 --- a/core/HandBrakeInternal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* $Id: HandBrakeInternal.h,v 1.2 2003/11/04 15:44:24 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_HANDBRAKE_INTERNAL_H -#define HB_HANDBRAKE_INTERNAL_H - -#include "HandBrake.h" - -/* Called by HBScan to tell the GUI how far we are */ -void HBScanning( HBHandle *, int title ); - -/* Called by HBScan. titleList is a list of all valid titles which - should be shown on the interface */ -void HBScanDone( HBHandle *, HBList * titleList ); - -/* Used to create temporary files (/tmp/HB.pid.whatever) */ -int HBGetPid( HBHandle * ); - -/* Called by every thread involved in the rip process. Returns - immediately is rip isn't paused, blocks if it is */ -void HBCheckPaused( HBHandle * ); - -/* Called by the decoders when the last packet is being proceeded */ -void HBDone( HBHandle * ); - -/* Called by the video encoder to update the GUI progress */ -void HBPosition( HBHandle *, float ); - -/* Called by any thread which couldn't continue and ask to stop */ -void HBErrorOccured( HBHandle *, HBError ); - -#endif diff --git a/core/Jamfile b/core/Jamfile new file mode 100644 index 000000000..d33688722 --- /dev/null +++ b/core/Jamfile @@ -0,0 +1,47 @@ +# $Id: Jamfile,v 1.5 2004/01/16 19:04:04 titer Exp $ +# +# This file is part of the HandBrake source code. +# Homepage: <http://handbrake.m0k.org/>. +# It may be used under the terms of the GNU General Public License. + +SubDir TOP core ; + +SOURCES_HBCORE = +Ac3Dec.c +AviMux.c +DVDRead.c +FaacEnc.c +FfmpegEnc.c +Fifo.c +HandBrake.c +MadDec.c +Mp3Enc.c +Mp4Mux.c +Mpeg2Dec.c +OgmMux.c +Scale.c +Scan.c +Thread.c +Utils.c +VorbisEnc.c +Work.c +X264Enc.c +XvidEnc.c ; + +ObjectCcFlags $(SOURCES_HBCORE) : + -I$(TOP)/contrib/liba52 + -I$(TOP)/contrib/libavcodec + -I$(TOP)/contrib/libdvdplay + -I$(TOP)/contrib/libdvdread + -I$(TOP)/contrib/libfaac + -I$(TOP)/contrib/libmp3lame + -I$(TOP)/contrib/libmp4v2 + -I$(TOP)/contrib/libmpeg2 + -I$(TOP)/contrib/libogg + -I$(TOP)/contrib/libvorbis + -I$(TOP)/contrib/libx264 + -I$(TOP)/contrib/libxvidcore + -g -Wall ; + +Library libhb.a : $(SOURCES_HBCORE) ; + diff --git a/core/MadDec.c b/core/MadDec.c index deecfeebd..da79ad886 100644 --- a/core/MadDec.c +++ b/core/MadDec.c @@ -1,9 +1,8 @@ -/* $Id: MadDec.c,v 1.1 2003/11/03 12:08:01 titer Exp $ +/* $Id: MadDec.c,v 1.2 2003/12/26 20:03:27 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "MadDec.h" -#include "Fifo.h" +#include "HBInternal.h" diff --git a/core/MadDec.h b/core/MadDec.h deleted file mode 100644 index b1624338f..000000000 --- a/core/MadDec.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: MadDec.h,v 1.1 2003/11/03 12:08:01 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_MAD_DEC_H -#define HB_MAD_DEC_H - -#include "HandBrakeInternal.h" - -HBMadDec * HBMadDecInit( HBHandle *, HBAudio * ); -void HBMadDecClose( HBMadDec * ); - -#endif diff --git a/core/Mp3Enc.c b/core/Mp3Enc.c index 70693467f..bd62df4ae 100644 --- a/core/Mp3Enc.c +++ b/core/Mp3Enc.c @@ -1,20 +1,15 @@ -/* $Id: Mp3Enc.c,v 1.5 2003/11/07 21:52:57 titer Exp $ +/* $Id: Mp3Enc.c,v 1.13 2004/01/21 17:59:33 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "Fifo.h" -#include "Mp3Enc.h" -#include "Work.h" +#include "HBInternal.h" -#include <lame/lame.h> +/* libmp3lame */ +#include "lame/lame.h" -/* Local prototypes */ -static int Mp3EncWork( HBWork * ); -static int GetBytes( HBMp3Enc * ); - -struct HBMp3Enc +typedef struct HBMp3Enc { HB_WORK_COMMON_MEMBERS @@ -24,17 +19,25 @@ struct HBMp3Enc HBBuffer * rawBuffer; int rawBufferPos; float position; - int samplesNeeded; + int inputSamples; int samplesGot; float * left; float * right; HBBuffer * mp3Buffer; -}; -HBMp3Enc * HBMp3EncInit( HBHandle * handle, HBAudio * audio ) + /* Stats */ + int64_t samples; + int64_t bytes; +} HBMp3Enc; + +/* Local prototypes */ +static int Mp3EncWork( HBWork * ); +static int GetSamples( HBMp3Enc * ); + +HBWork * HBMp3EncInit( HBHandle * handle, HBAudio * audio ) { HBMp3Enc * m; - if( !( m = malloc( sizeof( HBMp3Enc ) ) ) ) + if( !( m = calloc( sizeof( HBMp3Enc ), 1 ) ) ) { HBLog( "HBMp3EncInit: malloc() failed, gonna crash" ); return NULL; @@ -42,31 +45,35 @@ HBMp3Enc * HBMp3EncInit( HBHandle * handle, HBAudio * audio ) m->name = strdup( "Mp3Enc" ); m->work = Mp3EncWork; - + m->handle = handle; m->audio = audio; - m->globalFlags = NULL; - m->rawBuffer = NULL; - m->rawBufferPos = 0; - m->position = 0.0; - m->samplesNeeded = 0; - m->samplesGot = 0; - m->left = NULL; - m->right = NULL; - m->mp3Buffer = NULL; - - return m; + + return (HBWork*) m; } -void HBMp3EncClose( HBMp3Enc ** _m ) +void HBMp3EncClose( HBWork ** _m ) { - HBMp3Enc * m = *_m; - + HBMp3Enc * m = (HBMp3Enc*) *_m; + if( m->globalFlags ) lame_close( m->globalFlags ); if( m->rawBuffer ) HBBufferClose( &m->rawBuffer ); if( m->left ) free( m->left ); if( m->right ) free( m->right ); if( m->mp3Buffer ) HBBufferClose( &m->mp3Buffer ); + + if( m->samples ) + { + int64_t bytes = 128 * m->audio->outBitrate * m->samples / + m->audio->inSampleRate; + float bitrate = (float) m->bytes * m->audio->inSampleRate / + m->samples / 128; + + HBLog( "HBMp3Enc: %lld samples encoded (%lld bytes), %.2f kbps", + m->samples, m->bytes, bitrate ); + HBLog( "HBFaacEnc: error is %lld bytes", m->bytes - bytes ); + } + free( m->name ); free( m ); @@ -86,7 +93,7 @@ static int Mp3EncWork( HBWork * w ) if( !m->globalFlags ) { int i; - + /* Get a first buffer so we know that audio->inSampleRate is correct */ if( ( m->rawBuffer = HBFifoPop( audio->rawFifo ) ) ) @@ -105,7 +112,8 @@ static int Mp3EncWork( HBWork * w ) outSampleRate, we will give ( 1152 * inSampleRate ) / ( 2 * outSampleRate ) samples to libmp3lame so we are sure we will never get more than 1 frame at a time */ - m->samplesNeeded = 1152 * audio->inSampleRate / + audio->outSampleRate = 44100; + m->inputSamples = 1152 * audio->inSampleRate / audio->outSampleRate / 2; HBLog( "HBMp3Enc: opening lame (%d->%d Hz, %d kbps)", @@ -123,15 +131,15 @@ static int Mp3EncWork( HBWork * w ) return didSomething; } - m->left = malloc( m->samplesNeeded * sizeof( float ) ); - m->right = malloc( m->samplesNeeded * sizeof( float ) ); + m->left = malloc( m->inputSamples * sizeof( float ) ); + m->right = malloc( m->inputSamples * sizeof( float ) ); if( !m->left || !m->right ) { HBLog( "HBMp3Enc: malloc() failed, gonna crash" ); } - for( i = 0; i < m->samplesNeeded; i++ ) + for( i = 0; i < m->inputSamples; i++ ) { m->left[i] = 0.0; m->right[i] = 0.0; @@ -141,7 +149,7 @@ static int Mp3EncWork( HBWork * w ) /* Push encoded buffer */ if( m->mp3Buffer ) { - if( HBFifoPush( audio->mp3Fifo, &m->mp3Buffer ) ) + if( HBFifoPush( audio->outFifo, &m->mp3Buffer ) ) { didSomething = 1; } @@ -156,12 +164,12 @@ static int Mp3EncWork( HBWork * w ) if( audio->delay > 0 ) { /* Audio starts later - insert some silence */ - int length = m->samplesNeeded * 1000 / audio->inSampleRate; - + int length = m->inputSamples * 1000 / audio->inSampleRate; + if( audio->delay > length ) { HBLog( "HBMp3Enc: adding %d ms of silence", length ); - m->samplesGot = m->samplesNeeded; + m->samplesGot = m->inputSamples; audio->delay -= length; } else @@ -172,11 +180,11 @@ static int Mp3EncWork( HBWork * w ) else if( audio->delay < 0 ) { /* Audio starts sooner - trash some */ - int length = m->samplesNeeded * 1000 / audio->inSampleRate; + int length = m->inputSamples * 1000 / audio->inSampleRate; if( - audio->delay > length ) { - if( GetBytes( m ) ) + if( GetSamples( m ) ) { didSomething = 1; HBLog( "HBMp3Enc: trashing %d ms", length ); @@ -196,7 +204,7 @@ static int Mp3EncWork( HBWork * w ) } /* Get new samples */ - if( GetBytes( m ) ) + if( GetSamples( m ) ) { didSomething = 1; } @@ -209,9 +217,11 @@ static int Mp3EncWork( HBWork * w ) mp3Buffer = HBBufferInit( LAME_MAXMP3BUFFER ); ret = lame_encode_buffer_float( m->globalFlags, m->left, - m->right, m->samplesNeeded, + m->right, m->inputSamples, mp3Buffer->data, mp3Buffer->size ); + /* Stats */ + m->samples += m->inputSamples; if( ret < 0 ) { @@ -232,19 +242,21 @@ static int Mp3EncWork( HBWork * w ) mp3Buffer->size = ret; mp3Buffer->keyFrame = 1; mp3Buffer->position = m->position; - m->mp3Buffer = mp3Buffer; + + /* Stats */ + m->bytes += ret; } return didSomething; } -static int GetBytes( HBMp3Enc * m ) +static int GetSamples( HBMp3Enc * m ) { - while( m->samplesGot < m->samplesNeeded ) + while( m->samplesGot < m->inputSamples ) { int i; - + if( !m->rawBuffer ) { if( !( m->rawBuffer = HBFifoPop( m->audio->rawFifo ) ) ) @@ -256,22 +268,20 @@ static int GetBytes( HBMp3Enc * m ) m->position = m->rawBuffer->position; } - i = MIN( m->samplesNeeded - m->samplesGot, - ( m->rawBuffer->size / 2 - - m->rawBufferPos ) / sizeof( float ) ); + i = MIN( m->inputSamples - m->samplesGot, + m->rawBuffer->samples - m->rawBufferPos ); memcpy( m->left + m->samplesGot, - m->rawBuffer->data + m->rawBufferPos, + m->rawBuffer->left + m->rawBufferPos, i * sizeof( float ) ); memcpy( m->right + m->samplesGot, - m->rawBuffer->data + m->rawBuffer->size / 2 + - m->rawBufferPos, + m->rawBuffer->right + m->rawBufferPos, i * sizeof( float ) ); m->samplesGot += i; - m->rawBufferPos += i * sizeof( float ); + m->rawBufferPos += i; - if( m->rawBufferPos == m->rawBuffer->size / 2 ) + if( m->rawBufferPos == m->rawBuffer->samples ) { HBBufferClose( &m->rawBuffer ); } diff --git a/core/Mp3Enc.h b/core/Mp3Enc.h deleted file mode 100644 index db02f4f44..000000000 --- a/core/Mp3Enc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: Mp3Enc.h,v 1.1 2003/11/03 12:08:01 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_MP3_ENCODER_H -#define HB_MP3_ENCODER_H - -#include "HandBrakeInternal.h" - -HBMp3Enc * HBMp3EncInit( HBHandle *, HBAudio * ); -void HBMp3EncClose( HBMp3Enc ** ); - -#endif diff --git a/core/Mp4Mux.c b/core/Mp4Mux.c new file mode 100644 index 000000000..f780cab01 --- /dev/null +++ b/core/Mp4Mux.c @@ -0,0 +1,210 @@ +/* $Id: Mp4Mux.c,v 1.22 2004/02/18 17:07:20 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "HBInternal.h" + +/* libmp4v2 */ +#include "mp4.h" + +int64_t videoFrames; +int64_t videoBytes; +int64_t audioFrames; +int64_t audioBytes; + +/* Local prototypes */ +static void Mp4MuxThread( void * ); + +struct HBMp4Mux +{ + HBHandle * handle; + HBTitle * title; + + volatile int die; + HBThread * thread; +}; + +HBMp4Mux * HBMp4MuxInit( HBHandle * handle, HBTitle * title ) +{ + HBMp4Mux * m; + if( !( m = malloc( sizeof( HBMp4Mux ) ) ) ) + { + HBLog( "HBMp4MuxInit: malloc() failed, gonna crash" ); + return NULL; + } + + videoFrames = 0; + videoBytes = 0; + audioFrames = 0; + audioBytes = 0; + + m->handle = handle; + m->title = title; + + m->die = 0; + m->thread = HBThreadInit( "mp4 muxer", Mp4MuxThread, m, + HB_NORMAL_PRIORITY ); + return m; +} + +void HBMp4MuxClose( HBMp4Mux ** _m ) +{ + HBMp4Mux * m = *_m; + FILE * file; + long size; + + m->die = 1; + HBThreadClose( &m->thread ); + + file = fopen( m->title->file, "r" ); + fseek( file, 0, SEEK_END ); + size = ftell( file ); + fclose( file ); + + HBLog( "HBMp4Mux: videoFrames=%lld, %lld bytes", videoFrames, videoBytes ); + HBLog( "HBMp4Mux: audioFrames=%lld, %lld bytes", audioFrames, audioBytes ); + HBLog( "HBMp4Mux: overhead=%.2f bytes / frame", + ( (float) size - videoBytes - audioBytes ) / + ( videoFrames + audioFrames ) ); + + free( m ); + + *_m = NULL; +} + +static void Mp4MuxThread( void * _m ) +{ + HBMp4Mux * m = (HBMp4Mux*) _m; + HBTitle * title = m->title; + HBAudio * audio; + HBBuffer * buffer; + char tmpFile[1024]; + + int audioCount = HBListCount( m->title->ripAudioList ); + int i; + + MP4FileHandle file; + + /* Wait until we have one encoded frame for each track */ + while( !m->die && !HBFifoSize( title->outFifo ) ) + { + HBSnooze( 10000 ); + } + for( i = 0; i < audioCount; i++ ) + { + audio = HBListItemAt( title->ripAudioList, i ); + while( !m->die && !HBFifoSize( audio->outFifo ) ) + { + HBSnooze( 10000 ); + } + } + + if( m->die ) + { + return; + } + + /* Write file headers */ + file = MP4Create( title->file, 0, 0 ); + MP4SetTimeScale( file, 90000 ); + title->track = MP4AddVideoTrack( file, 90000, + MP4_INVALID_DURATION, + title->outWidth, title->outHeight, + MP4_MPEG4_VIDEO_TYPE ); + MP4SetVideoProfileLevel( file, 0x03 ); + MP4SetTrackESConfiguration( file, title->track, title->esConfig, + title->esConfigLength ); + + for( i = 0; i < audioCount; i++ ) + { + audio = HBListItemAt( title->ripAudioList, i ); + audio->track = MP4AddAudioTrack( file, audio->outSampleRate, + 1024, MP4_MPEG4_AUDIO_TYPE ); + MP4SetAudioProfileLevel( file, 0x0F ); + MP4SetTrackESConfiguration( file, audio->track, audio->esConfig, + audio->esConfigLength ); + } + + for( ;; ) + { + /* Wait until we have one encoded frame for each track */ + if( !HBFifoWait( title->outFifo ) ) + { + m->die = 1; + break; + } + for( i = 0; i < audioCount; i++ ) + { + audio = HBListItemAt( title->ripAudioList, i ); + if( !HBFifoWait( audio->outFifo ) ) + { + m->die = 1; + break; + } + } + + if( m->die ) + { + break; + } + + /* Interleave frames in the same order than they were in the + original MPEG stream */ + audio = NULL; + for( i = 0; i < audioCount; i++ ) + { + HBAudio * otherAudio; + otherAudio = HBListItemAt( title->ripAudioList, i ); + if( !audio || HBFifoPosition( otherAudio->outFifo ) < + HBFifoPosition( audio->outFifo ) ) + { + audio = otherAudio; + } + } + + if( !audio || HBFifoPosition( title->outFifo ) < + HBFifoPosition( audio->outFifo ) ) + { + buffer = HBFifoPop( title->outFifo ); + MP4WriteSample( file, title->track, buffer->data, + buffer->size, + (uint64_t) 90000 * title->rateBase / title->rate, + 0, buffer->keyFrame ); + videoFrames++; + videoBytes += buffer->size; + HBBufferClose( &buffer ); + } + else + { + buffer = HBFifoPop( audio->outFifo ); + MP4WriteSample( file, audio->track, buffer->data, + buffer->size, MP4_INVALID_DURATION, + 0, buffer->keyFrame ); + audioFrames++; + audioBytes += buffer->size; + HBBufferClose( &buffer ); + } + } + + MP4Close( file ); + + if( !MP4MakeIsmaCompliant( title->file, 0 /*MP4_DETAILS_ALL*/, 1 ) ) + { + HBLog( "HBMp4Mux: MP4MakeIsmaCompliant() failed" ); + } + + sprintf( tmpFile, "%s.tmp", title->file ); + tmpFile[strlen( title->file ) + 4] = '\0'; + if( !MP4Optimize( title->file, tmpFile, 0 /*MP4_DETAILS_ALL*/ ) ) + { + HBLog( "HBMp4Mux: MP4Optimize() failed" ); + unlink( tmpFile ); + } + else + { + rename( tmpFile, title->file ); + } +} + diff --git a/core/Mpeg2Dec.c b/core/Mpeg2Dec.c index fb81f8080..ea3ffa2e4 100644 --- a/core/Mpeg2Dec.c +++ b/core/Mpeg2Dec.c @@ -1,19 +1,14 @@ -/* $Id: Mpeg2Dec.c,v 1.4 2003/11/12 21:46:59 titer Exp $ +/* $Id: Mpeg2Dec.c,v 1.12 2004/01/16 19:04:04 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "Fifo.h" -#include "Mpeg2Dec.h" -#include "Work.h" +#include "HBInternal.h" -#include <mpeg2dec/mpeg2.h> +#include "mpeg2dec/mpeg2.h" -/* Local prototypes */ -static int Mpeg2DecWork( HBWork * ); - -struct HBMpeg2Dec +typedef struct HBMpeg2Dec { HB_WORK_COMMON_MEMBERS @@ -24,9 +19,12 @@ struct HBMpeg2Dec mpeg2dec_t * libmpeg2; const mpeg2_info_t * info; int lateField; -}; +} HBMpeg2Dec; + +/* Local prototypes */ +static int Mpeg2DecWork( HBWork * ); -HBMpeg2Dec * HBMpeg2DecInit( HBHandle * handle, HBTitle * title ) +HBWork * HBMpeg2DecInit( HBHandle * handle, HBTitle * title ) { HBMpeg2Dec * m ; if( !( m = malloc( sizeof( HBMpeg2Dec ) ) ) ) @@ -47,15 +45,15 @@ HBMpeg2Dec * HBMpeg2DecInit( HBHandle * handle, HBTitle * title ) m->info = NULL; m->lateField = 0; - return m; + return (HBWork*) m; } -void HBMpeg2DecClose( HBMpeg2Dec ** _m ) +void HBMpeg2DecClose( HBWork ** _m ) { HBBuffer * buffer; - - HBMpeg2Dec * m = *_m; - + + HBMpeg2Dec * m = (HBMpeg2Dec*) *_m; + if( m->libmpeg2 ) { HBLog( "HBMpeg2Dec: closing libmpeg2 (pass %d)", m->pass ); @@ -69,7 +67,7 @@ void HBMpeg2DecClose( HBMpeg2Dec ** _m ) HBListClose( &m->rawBufferList ); free( m->name ); free( m ); - + *_m = NULL; } @@ -81,7 +79,7 @@ static int Mpeg2DecWork( HBWork * w ) HBBuffer * rawBuffer; HBBuffer * tmpBuffer; mpeg2_state_t state; - + int didSomething = 0; /* Push decoded buffers */ @@ -101,7 +99,7 @@ static int Mpeg2DecWork( HBWork * w ) } /* Get a new buffer to decode */ - if( ( mpeg2Buffer = HBFifoPop( title->mpeg2Fifo ) ) ) + if( ( mpeg2Buffer = HBFifoPop( title->inFifo ) ) ) { didSomething = 1; } @@ -122,6 +120,9 @@ static int Mpeg2DecWork( HBWork * w ) m->pass = mpeg2Buffer->pass; HBLog( "HBMpeg2Dec: opening libmpeg2 (pass %d)", m->pass ); +#ifdef HB_NOMMX + mpeg2_accel( 0 ); +#endif m->libmpeg2 = mpeg2_init(); m->info = mpeg2_info( m->libmpeg2 ); m->lateField = 0; @@ -143,7 +144,7 @@ static int Mpeg2DecWork( HBWork * w ) m->info->display_fbuf ) { rawBuffer = HBBufferInit( 3 * title->inWidth * - title->outWidth ); + title->inHeight ); /* TODO: make libmpeg2 write directly in our buffer */ memcpy( rawBuffer->data, m->info->display_fbuf->buf[0], @@ -164,16 +165,12 @@ static int Mpeg2DecWork( HBWork * w ) /* NTSC pulldown kludge */ if( m->info->display_picture->nb_fields == 3 ) { - if( m->lateField ) - { - tmpBuffer = HBBufferInit( rawBuffer->size ); - tmpBuffer->position = rawBuffer->position; - tmpBuffer->pass = rawBuffer->pass; - memcpy( tmpBuffer->data, rawBuffer->data, - tmpBuffer->size ); - HBListAdd( m->rawBufferList, tmpBuffer ); - } - m->lateField = !m->lateField; + rawBuffer->repeat = m->lateField; + m->lateField = !m->lateField; + } + else + { + rawBuffer->repeat = 0; } } else if( state == STATE_INVALID ) @@ -183,11 +180,6 @@ static int Mpeg2DecWork( HBWork * w ) } } - if( mpeg2Buffer->last ) - { - HBDone( m->handle ); - } - HBBufferClose( &mpeg2Buffer ); return didSomething; diff --git a/core/Mpeg2Dec.h b/core/Mpeg2Dec.h deleted file mode 100644 index af7f18c44..000000000 --- a/core/Mpeg2Dec.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: Mpeg2Dec.h,v 1.1 2003/11/03 12:08:01 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_MPEG2_DEC_H -#define HB_MPEG2_DEC_H - -#include "HandBrakeInternal.h" - -HBMpeg2Dec * HBMpeg2DecInit( HBHandle *, HBTitle * ); -void HBMpeg2DecClose( HBMpeg2Dec ** ); - -#endif diff --git a/core/OgmMux.c b/core/OgmMux.c new file mode 100644 index 000000000..d4712594b --- /dev/null +++ b/core/OgmMux.c @@ -0,0 +1,471 @@ +/* $Id: OgmMux.c,v 1.6 2004/02/13 15:12:09 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "HBInternal.h" + +#include <ogg/ogg.h> + +static void OgmMuxThread( void * ); +static int OgmStart( HBOgmMux * ); +static int OgmFlush( HBOgmMux *, int ); +static int OgmEnd( HBOgmMux * ); + +struct HBOgmMux +{ + HBHandle *handle; + HBTitle *title; + + volatile int die; + HBThread *thread; + + FILE *file; + + int i_tk; + struct + { + HBFifo *fifo; + + int codec; + + ogg_stream_state os; + int i_packet_no; + + } tk[100]; /* The first who set more than 100 stream !! */ +}; + +HBOgmMux * HBOgmMuxInit( HBHandle * handle, HBTitle * title ) +{ + HBOgmMux *ogm = malloc( sizeof( HBOgmMux ) ); + + ogm->handle = handle; + ogm->title = title; + + ogm->file = NULL; + ogm->i_tk = 0; + + ogm->die = 0; + ogm->thread = HBThreadInit( "ogm muxer", OgmMuxThread, ogm, HB_NORMAL_PRIORITY ); + return ogm; +} + +void HBOgmMuxClose( HBOgmMux ** _ogm ) +{ + HBOgmMux *ogm = *_ogm; + + ogm->die = 1; + HBThreadClose( &ogm->thread ); + + free( ogm ); + + *_ogm = NULL; +} + +static int OgmDataWait( HBOgmMux *ogm ) +{ + int i; + + for( i = 0; i < ogm->i_tk; i++ ) + { + while( !ogm->die && HBFifoSize( ogm->tk[i].fifo ) <= 0 ) + { + HBSnooze( 10000 ); + } + } + return ogm->die ? -1 : 0; +} + +static void OgmMuxThread( void * _this ) +{ + HBOgmMux *ogm = _this; + + HBTitle *title = ogm->title; + + int i; + + /* Open output file */ + if( ( ogm->file = fopen( title->file, "w" ) ) == NULL ) + { + HBLog( "HBOgmMux: failed to open `%s'", title->file ); + /* FIXME */ + HBErrorOccured( ogm->handle, HB_ERROR_AVI_WRITE ); + return; + } + HBLog( "HBOgmMux: `%s' opened", title->file ); + + + /* Wait for data in each fifo */ + HBLog( "HBOgmMux: waiting video/audio data" ); + if( OgmDataWait( ogm ) < 0 ) + { + HBLog( "HBOgmMux: exiting" ); + fclose( ogm->file ); + unlink( title->file ); + return; + } + + if( OgmStart( ogm ) < 0 ) + { + HBLog( "HBOgmMux: failed to write headers" ); + fclose( ogm->file ); + unlink( title->file ); + return; + } + + HBLog( "HBOgmMux: headers written" ); + + for( ;; ) + { + HBBuffer *buffer; + ogg_packet op; + int i_tk; + + /* Wait data */ + if( OgmDataWait( ogm ) < 0 ) + { + break; + } + + /* Choose the right track to write (interleaved data) */ + for( i = 0, i_tk = -1; i < ogm->i_tk; i++ ) + { + if( i_tk < 0 || + HBFifoPosition( ogm->tk[i].fifo ) < HBFifoPosition( ogm->tk[i_tk].fifo ) ) + { + i_tk = i; + } + } + + buffer = HBFifoPop( ogm->tk[i_tk].fifo ); + + switch( ( ogm->tk[i_tk].codec ) ) + { + case HB_CODEC_FFMPEG: + case HB_CODEC_XVID: + case HB_CODEC_X264: + op.bytes = buffer->size + 1; + op.packet = malloc( op.bytes ); + op.packet[0] = buffer->keyFrame ? 0x08 : 0x00; + memcpy( &op.packet[1], buffer->data, buffer->size ); + op.b_o_s = 0; + op.e_o_s = 0; + op.granulepos = ogm->tk[i_tk].i_packet_no; + op.packetno = ogm->tk[i_tk].i_packet_no++; + break; + case HB_CODEC_MP3: + op.bytes = buffer->size + 1; + op.packet = malloc( op.bytes ); + op.packet[0] = 0x08; + memcpy( &op.packet[1], buffer->data, buffer->size ); + op.b_o_s = 0; + op.e_o_s = 0; + op.granulepos = ogm->tk[i_tk].i_packet_no * 1152; + op.packetno = ogm->tk[i_tk].i_packet_no++; + break; + case HB_CODEC_VORBIS: + memcpy( &op, buffer->data, sizeof( ogg_packet ) ); + + op.packet = malloc( op.bytes ); + memcpy( op.packet, buffer->data + sizeof( ogg_packet ), op.bytes ); + break; + + default: + HBLog( "HBOgmMux: unhandled codec" ); + op.bytes = 0; + op.packet = NULL; + break; + } + + if( op.packet ) + { + ogg_stream_packetin( &ogm->tk[i_tk].os, &op ); + + for( ;; ) + { + ogg_page og; + if( ogg_stream_pageout( &ogm->tk[i_tk].os, &og ) == 0 ) + { + break; + } + + if( fwrite( og.header, og.header_len, 1, ogm->file ) <= 0 || + fwrite( og.body, og.body_len, 1, ogm->file ) <= 0 ) + { + HBLog( "HBOgmMux: write failed" ); + break; + } + } + free( op.packet ); + } + + HBBufferClose( &buffer ); + } + + if( OgmEnd( ogm ) < 0 ) + { + HBLog( "HBOgmMux: flush failed" ); + } + + fclose( ogm->file ); + HBLog( "HBOgmMux: `%s' closed", title->file ); +} + +typedef struct __attribute__((__packed__)) +{ + uint8_t i_packet_type; + + char stream_type[8]; + char sub_type[4]; + + int32_t i_size; + + int64_t i_time_unit; + int64_t i_samples_per_unit; + int32_t i_default_len; + + int32_t i_buffer_size; + int16_t i_bits_per_sample; + int16_t i_padding_0; // hum hum + union + { + struct + { + int32_t i_width; + int32_t i_height; + + } video; + struct + { + int16_t i_channels; + int16_t i_block_align; + int32_t i_avgbytespersec; + } audio; + } header; + +} ogg_stream_header_t; + +#define SetWLE( p, v ) _SetWLE( (uint8_t*)p, v) +static void _SetWLE( uint8_t *p, uint16_t i_dw ) +{ + p[1] = ( i_dw >> 8 )&0xff; + p[0] = ( i_dw )&0xff; +} + +#define SetDWLE( p, v ) _SetDWLE( (uint8_t*)p, v) +static void _SetDWLE( uint8_t *p, uint32_t i_dw ) +{ + p[3] = ( i_dw >> 24 )&0xff; + p[2] = ( i_dw >> 16 )&0xff; + p[1] = ( i_dw >> 8 )&0xff; + p[0] = ( i_dw )&0xff; +} +#define SetQWLE( p, v ) _SetQWLE( (uint8_t*)p, v) +static void _SetQWLE( uint8_t *p, uint64_t i_qw ) +{ + SetDWLE( p, i_qw&0xffffffff ); + SetDWLE( p+4, ( i_qw >> 32)&0xffffffff ); +} + +static int OgmFlush( HBOgmMux *ogm, int i_tk ) +{ + for( ;; ) + { + ogg_page og; + if( ogg_stream_flush( &ogm->tk[i_tk].os, &og ) == 0 ) + { + break; + } + if( fwrite( og.header, og.header_len, 1, ogm->file ) <= 0 || + fwrite( og.body, og.body_len, 1, ogm->file ) <= 0 ) + { + return -1; + } + } + return 0; +} + +static int OgmStart( HBOgmMux *ogm ) +{ + HBTitle *title = ogm->title; + int i; + + ogg_packet op; + + /* Init track */ + ogm->tk[0].codec = title->codec; + ogm->tk[0].fifo = title->outFifo; + ogm->tk[0].i_packet_no = 0; + ogg_stream_init (&ogm->tk[0].os, 0 ); + + for( i = 1; i < HBListCount( title->ripAudioList ) + 1; i++ ) + { + HBAudio *audio = HBListItemAt( title->ripAudioList, i - 1 ); + + ogm->tk[i].codec = audio->codec; + ogm->tk[i].fifo = audio->outFifo; + ogm->tk[i].i_packet_no = 0; + ogg_stream_init (&ogm->tk[i].os, i ); + + } + ogm->i_tk = 1 + HBListCount( title->ripAudioList ); + + /* Wait data for each track */ + for( i = 0; i < ogm->i_tk; i++ ) + { + while( !ogm->die && + ( ( ogm->tk[i].codec == HB_CODEC_VORBIS && HBFifoSize( ogm->tk[i].fifo ) <= 3 ) || + HBFifoSize( ogm->tk[i].fifo ) <= 0 ) ) + { + HBSnooze( 10000 ); + } + } + + if( ogm->die ) + { + return -1; + } + + /* First pass: all b_o_s packets */ + for( i = 0; i < ogm->i_tk; i++ ) + { + ogg_stream_header_t h; + + memset( &h, 0, sizeof( ogg_stream_header_t ) ); + + switch( ogm->tk[i].codec ) + { + case HB_CODEC_FFMPEG: + case HB_CODEC_XVID: + case HB_CODEC_X264: + h.i_packet_type = 0x01; + memcpy( h.stream_type, "video ", 8 ); + if( ogm->tk[i].codec == HB_CODEC_X264 ) + { + memcpy( h.sub_type, "H264", 4 ); + } + else + { + memcpy( h.sub_type, "XVID", 4 ); + } + + SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1); + SetQWLE( &h.i_time_unit, (int64_t)10*1000*1000*(int64_t)title->rateBase/(int64_t)title->rate ); + SetQWLE( &h.i_samples_per_unit, 1 ); + SetDWLE( &h.i_default_len, 0 ); + SetDWLE( &h.i_buffer_size, 1024*1024 ); + SetWLE ( &h.i_bits_per_sample, 0 ); + SetDWLE( &h.header.video.i_width, title->outWidth ); + SetDWLE( &h.header.video.i_height, title->outHeight ); + + op.packet = (char*)&h; + op.bytes = sizeof( ogg_stream_header_t ); + op.b_o_s = 1; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = ogm->tk[i].i_packet_no++; + ogg_stream_packetin( &ogm->tk[i].os, &op ); + break; + + case HB_CODEC_MP3: + { + HBAudio *audio = HBListItemAt( title->ripAudioList, i - 1 ); + + h.i_packet_type = 0x01; + memcpy( h.stream_type, "audio ", 8 ); + memcpy( h.sub_type, "55 ", 4 ); + + SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1); + SetQWLE( &h.i_time_unit, 0 ); + SetQWLE( &h.i_samples_per_unit, audio->outSampleRate ); + SetDWLE( &h.i_default_len, 1 ); + SetDWLE( &h.i_buffer_size, 30*1024 ); + SetWLE ( &h.i_bits_per_sample, 0 ); + + SetDWLE( &h.header.audio.i_channels, 2 ); + SetDWLE( &h.header.audio.i_block_align, 0 ); + SetDWLE( &h.header.audio.i_avgbytespersec, audio->outBitrate / 8 ); + + + op.packet = (char*)&h; + op.bytes = sizeof( ogg_stream_header_t ); + op.b_o_s = 1; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = ogm->tk[i].i_packet_no++; + ogg_stream_packetin( &ogm->tk[i].os, &op ); + break; + } + case HB_CODEC_VORBIS: + { + HBBuffer *h = HBFifoPop( ogm->tk[i].fifo ); + + memcpy( &op, h->data, sizeof( ogg_packet ) ); + op.packet = h->data + sizeof( ogg_packet ); + ogg_stream_packetin( &ogm->tk[i].os, &op ); + break; + } + case HB_CODEC_AAC: + break; + default: + HBLog( "unhandled codec" ); + break; + } + OgmFlush( ogm, i ); + } + + /* second pass: all non b_o_s packets */ + for( i = 0; i < ogm->i_tk; i++ ) + { + if( ogm->tk[i].codec == HB_CODEC_VORBIS ) + { + HBBuffer *h; + int j; + + for( j = 0; j < 2; j++ ) + { + HBFifoWait( ogm->tk[i].fifo ); + h = HBFifoPop( ogm->tk[i].fifo ); + + memcpy( &op, h->data, sizeof( ogg_packet ) ); + op.packet = h->data + sizeof( ogg_packet ); + ogg_stream_packetin( &ogm->tk[i].os, &op ); + + OgmFlush( ogm, i ); + } + } +#if 0 + else + { + /* Home made commentary */ + op.packet = "\003Handbrake"; + op.bytes = strlen( "\003Handbrake" );; + op.b_o_s = 0; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = ogm->tk[i].i_packet_no++; + + ogg_stream_packetin( &ogm->tk[i].os, &op ); + OgmFlush( ogm, i ); + } +#endif + } + + return 0; +} + +static int OgmEnd( HBOgmMux *ogm ) +{ + int i; + + for( i = 0; i < ogm->i_tk; i++ ) + { + if( OgmFlush( ogm, i ) < 0 ) + { + return -1; + } + } + return 0; +} + diff --git a/core/Scale.c b/core/Scale.c index 7e9295962..464623c1e 100644 --- a/core/Scale.c +++ b/core/Scale.c @@ -1,19 +1,14 @@ -/* $Id: Scale.c,v 1.4 2003/11/06 13:03:19 titer Exp $ +/* $Id: Scale.c,v 1.9 2004/01/16 19:39:23 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "Fifo.h" -#include "Scale.h" -#include "Work.h" +#include "HBInternal.h" -#include <ffmpeg/avcodec.h> +#include "ffmpeg/avcodec.h" -/* Local prototypes */ -static int ScaleWork( HBWork * ); - -struct HBScale +typedef struct HBScale { HB_WORK_COMMON_MEMBERS @@ -24,11 +19,14 @@ struct HBScale AVPicture rawPicture; HBBuffer * deintBuffer; AVPicture deintPicture; - HBBuffer * scaledBuffer; + HBList * scaledBufferList; AVPicture scaledPicture; -}; +} HBScale; -HBScale * HBScaleInit( HBHandle * handle, HBTitle * title ) +/* Local prototypes */ +static int ScaleWork( HBWork * ); + +HBWork * HBScaleInit( HBHandle * handle, HBTitle * title ) { HBScale * s; if( !( s = malloc( sizeof( HBScale ) ) ) ) @@ -51,25 +49,26 @@ HBScale * HBScaleInit( HBHandle * handle, HBTitle * title ) title->leftCrop, title->rightCrop ); /* Allocate a constant buffer used for deinterlacing */ - s->deintBuffer = HBBufferInit( 3 * title->inWidth * + s->deintBuffer = HBBufferInit( 3 * title->inWidth * title->inHeight / 2 ); avpicture_fill( &s->deintPicture, s->deintBuffer->data, PIX_FMT_YUV420P, title->inWidth, title->inHeight ); - s->scaledBuffer = NULL; + s->scaledBufferList = HBListInit(); - return s; + return (HBWork*) s; } -void HBScaleClose( HBScale ** _s ) +void HBScaleClose( HBWork ** _s ) { - HBScale * s = *_s; - + HBScale * s = (HBScale*) *_s; + img_resample_close( s->context ); + HBListClose( &s->scaledBufferList ); HBBufferClose( &s->deintBuffer ); free( s->name ); free( s ); - + *_s = NULL; } @@ -78,15 +77,20 @@ static int ScaleWork( HBWork * w ) HBScale * s = (HBScale*) w; HBTitle * title = s->title; HBBuffer * rawBuffer; + HBBuffer * scaledBuffer; + HBBuffer * tmpBuffer; int didSomething = 0; - /* Push scaled buffer */ - if( s->scaledBuffer ) + /* Push scaled buffer(s) */ + while( ( scaledBuffer = (HBBuffer*) + HBListItemAt( s->scaledBufferList, 0 ) ) ) { - if( HBFifoPush( title->scaledFifo, &s->scaledBuffer ) ) + tmpBuffer = scaledBuffer; + if( HBFifoPush( title->scaledFifo, &scaledBuffer ) ) { didSomething = 1; + HBListRemove( s->scaledBufferList, tmpBuffer ); } else { @@ -105,15 +109,15 @@ static int ScaleWork( HBWork * w ) } /* Allocate new buffer for the scaled picture */ - s->scaledBuffer = HBBufferInit( 3 * title->outWidth * - title->outHeight / 2 ); - s->scaledBuffer->position = rawBuffer->position; - s->scaledBuffer->pass = rawBuffer->pass; + scaledBuffer = HBBufferInit( 3 * title->outWidth * + title->outHeight / 2 ); + scaledBuffer->position = rawBuffer->position; + scaledBuffer->pass = rawBuffer->pass; /* libavcodec stuff */ avpicture_fill( &s->rawPicture, rawBuffer->data, PIX_FMT_YUV420P, title->inWidth, title->inHeight ); - avpicture_fill( &s->scaledPicture, s->scaledBuffer->data, + avpicture_fill( &s->scaledPicture, scaledBuffer->data, PIX_FMT_YUV420P, title->outWidth, title->outHeight ); @@ -131,9 +135,22 @@ static int ScaleWork( HBWork * w ) img_resample( s->context, &s->scaledPicture, &s->rawPicture ); } + HBListAdd( s->scaledBufferList, scaledBuffer ); + + if( rawBuffer->repeat ) + { + tmpBuffer = HBBufferInit( scaledBuffer->size ); + tmpBuffer->position = scaledBuffer->position; + tmpBuffer->pass = scaledBuffer->pass; + memcpy( tmpBuffer->data, scaledBuffer->data, + scaledBuffer->size ); + + HBListAdd( s->scaledBufferList, tmpBuffer ); + } + /* Free memory */ HBBufferClose( &rawBuffer ); - + return didSomething; } diff --git a/core/Scale.h b/core/Scale.h deleted file mode 100644 index cf06ad661..000000000 --- a/core/Scale.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: Scale.h,v 1.1 2003/11/03 12:08:01 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_SCALE_H -#define HB_SCALE_H - -#include "HandBrakeInternal.h" - -HBScale * HBScaleInit( HBHandle *, HBTitle * ); -void HBScaleClose( HBScale ** ); - -#endif diff --git a/core/Scan.c b/core/Scan.c index 7a62a97e0..f2afd5e6c 100644 --- a/core/Scan.c +++ b/core/Scan.c @@ -1,21 +1,19 @@ -/* $Id: Scan.c,v 1.5 2003/11/09 21:28:22 titer Exp $ +/* $Id: Scan.c,v 1.14 2004/01/18 13:21:12 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "Fifo.h" +#include "HBInternal.h" #include "Languages.h" -#include "Scan.h" -#include "Thread.h" -#include <dvdread/ifo_types.h> -#include <dvdplay/dvdplay.h> -#include <dvdplay/info.h> -#include <dvdplay/state.h> -#include <dvdplay/nav.h> +#include "dvdread/ifo_types.h" +#include "dvdplay/dvdplay.h" +#include "dvdplay/info.h" +#include "dvdplay/state.h" +#include "dvdplay/nav.h" -#include <mpeg2dec/mpeg2.h> +#include "mpeg2dec/mpeg2.h" /* Local prototypes */ static void ScanThread( void * ); @@ -26,14 +24,14 @@ static char * LanguageForCode( int code ); struct HBScan { - HBHandle * handle; - char * device; - int title; - int die; - HBThread * thread; + HBHandle * handle; + char * device; + int title; + volatile int die; + HBThread * thread; }; -HBScan * HBScanInit( HBHandle * handle, char * device, int title ) +HBScan * HBScanInit( HBHandle * handle, const char * device, int title ) { HBScan * s; if( !( s = malloc( sizeof( HBScan ) ) ) ) @@ -55,7 +53,7 @@ HBScan * HBScanInit( HBHandle * handle, char * device, int title ) void HBScanClose( HBScan ** _s ) { HBScan * s = *_s; - + s->die = 1; HBThreadClose( &s->thread ); @@ -66,65 +64,77 @@ void HBScanClose( HBScan ** _s ) static void ScanThread( void * _s ) { - HBScan * s = (HBScan*) _s; - dvdplay_ptr vmg; - HBList * titleList = HBListInit(); - HBTitle * title; - int i; + HBScan * s = (HBScan*) _s; + dvdplay_ptr vmg; + HBList * titleList = HBListInit(); + HBTitle * title; + int i; HBLog( "HBScan: opening device %s", s->device ); - HBScanning( s->handle, 0 ); vmg = dvdplay_open( s->device, NULL, NULL ); if( !vmg ) { HBLog( "HBScan: dvdplay_open() failed (%s)", s->device ); - HBScanDone( s->handle, titleList ); + HBListClose( &titleList ); + HBScanDone( s->handle, NULL ); return; } /* Detect titles */ - for( i = ( s->title ? s->title - 1 : 0 ); - i < ( s->title ? s->title : dvdplay_title_nr( vmg ) ); - i++ ) + i = s->title ? ( s->title - 1 ) : 0; + while( !s->die ) { - if( s->die ) + if( ( title = ScanTitle( s, vmg, i + 1 ) ) ) { - break; + HBListAdd( titleList, title ); } - - if( !( title = ScanTitle( s, vmg, i + 1 ) ) ) + if( s->title || i == dvdplay_title_nr( vmg ) - 1 ) { - continue; + break; } - - HBListAdd( titleList, title ); + i++; } HBLog( "HBScan: closing device %s", s->device ); dvdplay_close( vmg ); + if( s->die ) + { + while( ( title = HBListItemAt( titleList, 0 ) ) ) + { + HBListRemove( titleList, title ); + HBTitleClose( &title ); + } + HBListClose( &titleList ); + return; + } + + if( !HBListCount( titleList ) ) + { + HBListClose( &titleList ); + } HBScanDone( s->handle, titleList ); } static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) { - HBTitle * title; - int audio_nr, foo; + HBTitle * title; + int audio_nr, foo; audio_attr_t * attr; - HBAudio * audio; - int i; - uint8_t dummy[DVD_VIDEO_LB_LEN]; - - HBLog( "HBScan: scanning title %d", index ); - HBScanning( s->handle, index ); + HBAudio * audio; + int i; + uint8_t dummy[DVD_VIDEO_LB_LEN]; + + HBScanning( s->handle, index, dvdplay_title_nr( vmg ) ); title = HBTitleInit( s->device, index ); dvdplay_start( vmg, index ); /* Length */ title->length = dvdplay_title_time( vmg ); - HBLog( "HBScan: title length is %d seconds", title->length ); + HBLog( "HBScan: title %d: length is %d seconds", index, + title->length ); /* Discard titles under 10 seconds */ if( title->length < 10 ) @@ -139,9 +149,8 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) for( i = 0; i < audio_nr; i++ ) { - int id; - int j; - + int id, j; + if( s->die ) { break; @@ -156,13 +165,14 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) if( ( id & 0xF0FF ) != 0x80BD ) { - HBLog( "HBScan: non-AC3 audio track detected, ignoring" ); + HBLog( "HBScan: title %d: non-AC3 audio track detected, " + "ignoring", index ); continue; } /* Check if we don't already found an track with the same id */ audio = NULL; - for( j = 0; j < HBListCountItems( title->audioList ); j++ ) + for( j = 0; j < HBListCount( title->audioList ); j++ ) { audio = (HBAudio*) HBListItemAt( title->audioList, j ); if( id == audio->id ) @@ -177,28 +187,29 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) if( audio ) { - HBLog( "HBScan: discarding duplicate track %x", id ); + HBLog( "HBScan: title %d: discarding duplicate track %x", + index, id ); continue; } - attr = dvdplay_audio_attr( vmg, j ); + attr = dvdplay_audio_attr( vmg, j ); audio = HBAudioInit( id, LanguageForCode( attr->lang_code ) ); - HBLog( "HBScan: new language (%x, %s)", id, audio->language ); + HBLog( "HBScan: title %d: new language (%x, %s)", index, id, + audio->language ); HBListAdd( title->audioList, audio ); } /* Discard titles with no audio tracks */ - if( !HBListCountItems( title->audioList ) ) + if( !HBListCount( title->audioList ) ) { HBLog( "HBScan: ignoring title %d (no audio track)", index ); HBTitleClose( &title ); return NULL; } - /* Kludge : libdvdplay wants we to read a first block before seeking */ + /* Kludge : libdvdplay wants us to read a first block before seeking */ dvdplay_read( vmg, dummy, 1 ); - for( i = 0; i < 10; i++ ) { if( s->die ) @@ -215,6 +226,7 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) } } + /* Handle ratio */ if( title->inHeight * title->aspect > title->inWidth * VOUT_ASPECT_FACTOR ) { @@ -248,8 +260,9 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, mpeg2dec_t * handle; const mpeg2_info_t * info; mpeg2_state_t state; - char fileName[1024]; - FILE * file; + char fileName[1024]; + FILE * file; + int ret = 1; HBList * esBufferList = HBListInit(); HBBuffer * psBuffer = NULL; @@ -259,43 +272,34 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, dvdplay_seek( vmg, pictureStart ); /* Init libmpeg2 */ +#ifdef HB_NOMMX + mpeg2_accel( 0 ); +#endif handle = mpeg2_init(); info = mpeg2_info( handle ); - + /* Init the destination file */ memset( fileName, 0, 1024 ); - sprintf( fileName, "/tmp/HB.%d.%d.%d", HBGetPid( s->handle ), + sprintf( fileName, "/tmp/HB.%d.%d.%d", HBGetPid( s->handle ), title->index, which ); file = fopen( fileName, "w" ); -#define CLEANUP \ - while( ( esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 ) ) ) \ - { \ - HBListRemove( esBufferList, esBuffer ); \ - HBBufferClose( &esBuffer ); \ - } \ - HBListClose( &esBufferList ); \ - if( psBuffer ) HBBufferClose( &psBuffer ); \ - if( esBuffer ) HBBufferClose( &esBuffer ); \ - mpeg2_close( handle ); \ - fclose( file ) - for( ;; ) - { + { state = mpeg2_parse( handle ); if( state == STATE_BUFFER ) - { + { /* Free the previous buffer */ if( esBuffer ) - { + { HBBufferClose( &esBuffer ); } - + /* Get a new one */ while( !esBuffer ) { - while( !HBListCountItems( esBufferList ) ) + while( !HBListCount( esBufferList ) ) { psBuffer = HBBufferInit( DVD_VIDEO_LB_LEN ); if( dvdplay_read( vmg, psBuffer->data, 1 ) != 1 || @@ -303,18 +307,21 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, { HBLog( "HBScan: failed to get a valid PS " "packet" ); - CLEANUP; - return 0; + break; } if( dvdplay_position( vmg ) >= pictureEnd ) { HBLog( "HBScan: gone too far, aborting" ); - CLEANUP; - return 0; + break; } } + if( !HBListCount( esBufferList ) ) + { + break; + } + esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 ); HBListRemove( esBufferList, esBuffer ); @@ -324,27 +331,80 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, } } + if( !esBuffer ) + { + ret = 0; + break; + } + /* Feed libmpeg2 */ mpeg2_buffer( handle, esBuffer->data, esBuffer->data + esBuffer->size ); } else if( state == STATE_SEQUENCE ) { - /* Get size & framerate info */ - title->inWidth = info->sequence->width; - title->inHeight = info->sequence->height; - title->aspect = (uint64_t)info->sequence->display_width * - info->sequence->pixel_width * VOUT_ASPECT_FACTOR / - ( info->sequence->display_height * - info->sequence->pixel_height ); - title->rate = 27000000; - title->rateBase = info->sequence->frame_period; + if( !which ) + { + /* Get size & framerate info */ + title->inWidth = info->sequence->width; + title->inHeight = info->sequence->height; + title->aspect = (uint64_t)info->sequence->display_width * + info->sequence->pixel_width * VOUT_ASPECT_FACTOR / + ( info->sequence->display_height * + info->sequence->pixel_height ); + title->rate = 27000000; + title->rateBase = info->sequence->frame_period; + + title->autoTopCrop = title->inHeight / 2; + title->autoBottomCrop = title->inHeight / 2; + title->autoLeftCrop = title->inWidth / 2; + title->autoRightCrop = title->inWidth / 2; + } } else if( ( state == STATE_SLICE || state == STATE_END ) && ( info->display_fbuf ) && ( info->display_picture->flags & PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I ) { +#define Y info->display_fbuf->buf[0] +#define DARK 64 + /* Detect black borders */ + int i, j; + for( i = 0; i < title->inWidth; i++ ) + { + for( j = 0; j < title->autoTopCrop; j++ ) + if( Y[ j * title->inWidth + i ] > DARK ) + { + title->autoTopCrop = j; + break; + } + for( j = 0; j < title->autoBottomCrop; j++ ) + if( Y[ ( title->inHeight - j - 1 ) * + title->inWidth + i ] > DARK ) + { + title->autoBottomCrop = j; + break; + } + } + for( i = 0; i < title->inHeight; i++ ) + { + for( j = 0; j < title->autoLeftCrop; j++ ) + if( Y[ i * title->inWidth + j ] > DARK ) + { + title->autoLeftCrop = j; + break; + } + for( j = 0; j < title->autoRightCrop; j++ ) + if( Y[ i * title->inWidth + + title->inWidth - j - 1 ] > DARK ) + { + title->autoRightCrop = j; + break; + } + } +#undef Y +#undef DARK + /* Write the raw picture to a file */ fwrite( info->display_fbuf->buf[0], title->inWidth * title->inHeight, 1, file ); @@ -358,15 +418,25 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, { /* Reset libmpeg2 */ mpeg2_close( handle ); +#ifdef HB_NOMMX + mpeg2_accel( 0 ); +#endif handle = mpeg2_init(); } } - CLEANUP; - - return 1; + while( ( esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 ) ) ) + { + HBListRemove( esBufferList, esBuffer ); + HBBufferClose( &esBuffer ); + } + HBListClose( &esBufferList ); + if( psBuffer ) HBBufferClose( &psBuffer ); + if( esBuffer ) HBBufferClose( &esBuffer ); + mpeg2_close( handle ); + fclose( file ); -#undef CLEANUP + return ret; } static char * LanguageForCode( int code ) diff --git a/core/Scan.h b/core/Scan.h deleted file mode 100644 index 5cc8542e7..000000000 --- a/core/Scan.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: Scan.h,v 1.2 2003/11/06 13:03:19 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_SCAN_H -#define HB_SCAN_H - -#include "HandBrakeInternal.h" - -HBScan * HBScanInit( HBHandle *, char * device, int title ); -void HBScanClose( HBScan ** ); - -#endif diff --git a/core/Thread.c b/core/Thread.c index f0d8e628b..01af1b0b6 100644 --- a/core/Thread.c +++ b/core/Thread.c @@ -1,13 +1,10 @@ -/* $Id: Thread.c,v 1.5 2003/11/12 16:09:34 titer Exp $ +/* $Id: Thread.c,v 1.10 2004/01/14 21:37:25 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include "Thread.h" -#ifdef SYS_CYGWIN -# include <windows.h> -#endif struct HBThread { @@ -15,12 +12,12 @@ struct HBThread int priority; void (*function) ( void * ); void * arg; - -#if defined( SYS_BEOS ) + +#if defined( HB_BEOS ) int thread; -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) pthread_t thread; -#elif defined( SYS_CYGWIN ) +#elif defined( HB_CYGWIN ) HANDLE thread; #endif }; @@ -42,14 +39,14 @@ HBThread * HBThreadInit( char * name, void (* function)(void *), t->function = function; t->arg = arg; -#if defined( SYS_BEOS ) +#if defined( HB_BEOS ) t->thread = spawn_thread( (int32 (*)( void * )) ThreadFunc, name, priority, t ); resume_thread( t->thread ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) pthread_create( &t->thread, NULL, (void * (*)( void * )) ThreadFunc, t ); -#elif defined( SYS_CYGWIN ) +#elif defined( HB_CYGWIN ) t->thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunc, t, 0, NULL ); #endif @@ -64,7 +61,7 @@ static void ThreadFunc( void * _t ) { HBThread * t = (HBThread*) _t; -#if defined( SYS_MACOSX ) +#if defined( HB_MACOSX ) struct sched_param param; memset( ¶m, 0, sizeof( struct sched_param ) ); param.sched_priority = t->priority; @@ -80,13 +77,13 @@ static void ThreadFunc( void * _t ) void HBThreadClose( HBThread ** _t ) { HBThread * t = *_t; - -#if defined( SYS_BEOS ) + +#if defined( HB_BEOS ) long exitValue; wait_for_thread( t->thread, &exitValue ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) pthread_join( t->thread, NULL ); -#elif defined( SYS_CYGWIN ) +#elif defined( HB_CYGWIN ) WaitForSingleObject( t->thread, INFINITE ); #endif @@ -107,12 +104,12 @@ HBLock * HBLockInit() return NULL; } -#if defined( SYS_BEOS ) +#if defined( HB_BEOS ) l->sem = create_sem( 1, "sem" ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) pthread_mutex_init( &l->mutex, NULL ); -#elif defined( SYS_CYGWIN ) - /* TODO */ +#elif defined( HB_CYGWIN ) + l->mutex = CreateMutex( 0, FALSE, 0 ); #endif return l; @@ -121,16 +118,46 @@ HBLock * HBLockInit() void HBLockClose( HBLock ** _l ) { HBLock * l = *_l; - -#if defined( SYS_BEOS ) + +#if defined( HB_BEOS ) delete_sem( l->sem ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) pthread_mutex_destroy( &l->mutex ); -#elif defined( SYS_CYGWIN ) - /* TODO */ +#elif defined( HB_CYGWIN ) + CloseHandle( l->mutex ); #endif free( l ); *_l = NULL; } +HBCond * HBCondInit() +{ + HBCond * c = malloc( sizeof( HBCond ) ); + +#if defined( HB_BEOS ) + c->thread = -1; +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) + pthread_cond_init( &c->cond, NULL ); +#elif defined( HB_CYGWIN ) + /* TODO */ +#endif + + return c; +} + +void HBCondClose( HBCond ** _c ) +{ + HBCond * c = *_c; + +#if defined( HB_BEOS ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) + pthread_cond_destroy( &c->cond ); +#elif defined( HB_CYGWIN ) + /* TODO */ +#endif + free( c ); + + *_c = NULL; +} + diff --git a/core/Thread.h b/core/Thread.h index 58700aae1..4d6288e5b 100644 --- a/core/Thread.h +++ b/core/Thread.h @@ -1,4 +1,4 @@ -/* $Id: Thread.h,v 1.3 2003/11/06 15:51:36 titer Exp $ +/* $Id: Thread.h,v 1.8 2004/01/14 21:37:25 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -7,64 +7,125 @@ #ifndef HB_THREAD_H #define HB_THREAD_H -#if defined( SYS_BEOS ) +/* System headers */ +#if defined( HB_BEOS ) # include <OS.h> -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) # include <pthread.h> +#elif defined( HB_CYGWIN ) +# include <windows.h> #endif #include "Utils.h" -#if defined( SYS_BEOS ) +/* Thread priorities */ +#if defined( HB_BEOS ) # define HB_LOW_PRIORITY 5 # define HB_NORMAL_PRIORITY 10 -#elif defined( SYS_MACOSX ) +#elif defined( HB_MACOSX ) # define HB_LOW_PRIORITY 0 # define HB_NORMAL_PRIORITY 31 -#elif defined( SYS_LINUX ) || defined( SYS_CYGWIN ) +#elif defined( HB_LINUX ) || defined( HB_CYGWIN ) /* Actually unused */ # define HB_LOW_PRIORITY 0 # define HB_NORMAL_PRIORITY 0 #endif +/* Functions declarations */ HBThread * HBThreadInit( char * name, void (* function)(void *), void * arg, int priority ); void HBThreadClose( HBThread ** ); +HBLock * HBLockInit(); +static inline void HBLockLock( HBLock * ); +static inline void HBLockUnlock( HBLock * ); +void HBLockClose( HBLock ** ); + +HBCond * HBCondInit(); +static inline void HBCondWait( HBCond *, HBLock * ); +static inline void HBCondSignal( HBCond * ); +void HBCondClose( HBCond ** ); + +/* Inlined stuff */ struct HBLock { -#if defined( SYS_BEOS ) +#if defined( HB_BEOS ) sem_id sem; -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) pthread_mutex_t mutex; -#elif defined( SYS_CYGWIN ) - /* TODO */ +#elif defined( HB_CYGWIN ) + HANDLE mutex; #endif }; -HBLock * HBLockInit(); -static inline void HBLockLock( HBLock * ); -static inline void HBLockUnlock( HBLock * ); -void HBLockClose( HBLock ** ); - static inline void HBLockLock( HBLock * l ) { -#if defined( SYS_BEOS ) +#if defined( HB_BEOS ) acquire_sem( l->sem ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) pthread_mutex_lock( &l->mutex ); -#elif defined( SYS_CYGWIN ) - /* TODO */ +#elif defined( HB_CYGWIN ) + WaitForSingleObject( l->mutex, INFINITE ); #endif } static inline void HBLockUnlock( HBLock * l ) { -#if defined( SYS_BEOS ) +#if defined( HB_BEOS ) release_sem( l->sem ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) pthread_mutex_unlock( &l->mutex ); -#elif defined( SYS_CYGWIN ) +#elif defined( HB_CYGWIN ) + ReleaseMutex( l->mutex ); +#endif +} + +struct HBCond +{ +#if defined( HB_BEOS ) + int thread; +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) + pthread_cond_t cond; +#elif defined( HB_CYGWIN ) + /* TODO */ +#endif + +}; + +static inline void HBCondWait( HBCond * c, HBLock * lock ) +{ +#if defined( HB_BEOS ) + c->thread = find_thread( NULL ); + release_sem( lock->sem ); + suspend_thread( c->thread ); + acquire_sem( lock->sem ); + c->thread = -1; +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) + pthread_cond_wait( &c->cond, &lock->mutex ); +#elif defined( HB_CYGWIN ) + /* TODO */ +#endif +} + +static inline void HBCondSignal( HBCond * c ) +{ +#if defined( HB_BEOS ) + while( c->thread != -1 ) + { + thread_info info; + get_thread_info( c->thread, &info ); + if( info.state == B_THREAD_SUSPENDED ) + { + resume_thread( c->thread ); + break; + } + /* In case HBCondSignal is called between HBCondWait's + release_sem() and suspend_thread() lines, wait a bit */ + snooze( 5000 ); + } +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) + pthread_cond_signal( &c->cond ); +#elif defined( HB_CYGWIN ) /* TODO */ #endif } diff --git a/core/Utils.c b/core/Utils.c index 566979901..f9451bb9a 100644 --- a/core/Utils.c +++ b/core/Utils.c @@ -1,4 +1,4 @@ -/* $Id: Utils.c,v 1.8 2003/11/12 16:09:34 titer Exp $ +/* $Id: Utils.c,v 1.14 2004/01/16 19:04:04 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -7,7 +7,7 @@ #include <stdarg.h> #include <time.h> #include <sys/time.h> -#ifdef SYS_CYGWIN +#ifdef HB_CYGWIN # include <windows.h> #endif @@ -23,22 +23,22 @@ struct HBList void HBSnooze( int time ) { -#if defined( SYS_BEOS ) +#if defined( HB_BEOS ) snooze( time ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +#elif defined( HB_MACOSX ) || defined( HB_LINUX ) usleep( time ); -#elif defined( SYS_CYGWIN ) +#elif defined( HB_CYGWIN ) Sleep( time / 1000 ); #endif } void HBLog( char * log, ... ) { - char string[81]; - time_t _now; + char string[80]; + time_t _now; struct tm * now; - va_list args; - int ret; + va_list args; + int ret; if( !getenv( "HB_DEBUG" ) ) { @@ -47,13 +47,13 @@ void HBLog( char * log, ... ) /* Show the time */ _now = time( NULL ); - now = localtime( &_now ); + now = localtime( &_now ); sprintf( string, "[%02d:%02d:%02d] ", now->tm_hour, now->tm_min, now->tm_sec ); /* Convert the message to a string */ va_start( args, log ); - ret = vsnprintf( string + 11, 68, log, args ); + ret = vsnprintf( string + 11, 67, log, args ); va_end( args ); /* Add the end of line */ @@ -66,7 +66,7 @@ void HBLog( char * log, ... ) uint64_t HBGetDate() { -#ifndef SYS_CYGWIN +#ifndef HB_CYGWIN struct timeval tv; gettimeofday( &tv, NULL ); return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec ); @@ -112,11 +112,11 @@ int HBPStoES( HBBuffer ** _psBuffer, HBList * esBufferList ) while( pos + 6 < psBuffer->size && d[pos] == 0 && d[pos+1] == 0 && d[pos+2] == 0x1 ) { - uint32_t streamId; - uint32_t PES_packet_length; - uint32_t PES_packet_end; - uint32_t PES_header_d_length; - uint32_t PES_header_end; + int streamId; + int PES_packet_length; + int PES_packet_end; + int PES_header_d_length; + int PES_header_end; int hasPTS; uint64_t PTS = 0; @@ -163,11 +163,10 @@ int HBPStoES( HBBuffer ** _psBuffer, HBList * esBufferList ) /* Sanity check */ if( pos >= PES_packet_end ) { - HBLog( "HBPStoES: pos >= PES_packet_end" ); pos = PES_packet_end; continue; } - + /* Here we hit we ES payload */ esBuffer = HBBufferInit( PES_packet_end - pos ); @@ -183,6 +182,8 @@ int HBPStoES( HBBuffer ** _psBuffer, HBList * esBufferList ) pos = PES_packet_end; } +#undef d + HBBufferClose( _psBuffer ); return 1; @@ -204,14 +205,14 @@ HBList * HBListInit() free( l ); return NULL; } - + l->allocItems = HBLIST_DEFAULT_SIZE; l->nbItems = 0; - + return l; } -int HBListCountItems( HBList * l ) +int HBListCount( HBList * l ) { return l->nbItems; } @@ -278,7 +279,7 @@ void * HBListItemAt( HBList * l, int index ) void HBListClose( HBList ** _l ) { HBList * l = *_l; - + free( l->items ); free( l ); @@ -287,23 +288,32 @@ void HBListClose( HBList ** _l ) HBTitle * HBTitleInit( char * device, int index ) { - HBTitle * t = calloc( sizeof( HBTitle ), 1 ); + HBTitle * t; + + if( !( t = calloc( sizeof( HBTitle ), 1 ) ) ) + { + HBLog( "HBTitleInit: calloc() failed, gonna crash" ); + return NULL; + } + + t->device = strdup( device ); + t->index = index; + + t->codec = HB_CODEC_FFMPEG; + t->mux = HB_MUX_MP4; + + t->audioList = HBListInit(); + t->ripAudioList = HBListInit(); - t->device = strdup( device ); - t->index = index; + t->start = -1; - t->codec = HB_CODEC_FFMPEG; - t->bitrate = 1024; - - t->audioList = HBListInit(); - return t; } void HBTitleClose( HBTitle ** _t ) { HBTitle * t = *_t; - + HBAudio * audio; while( ( audio = HBListItemAt( t->audioList, 0 ) ) ) { @@ -311,7 +321,8 @@ void HBTitleClose( HBTitle ** _t ) HBAudioClose( &audio ); } HBListClose( &t->audioList ); - + HBListClose( &t->ripAudioList ); + if( t->file ) free( t->file ); free( t->device ); free( t ); @@ -322,30 +333,23 @@ void HBTitleClose( HBTitle ** _t ) HBAudio * HBAudioInit( int id, char * language ) { HBAudio * a; - if( !( a = malloc( sizeof( HBAudio ) ) ) ) + if( !( a = calloc( sizeof( HBAudio ), 1 ) ) ) { - HBLog( "HBAudioInit: malloc() failed, gonna crash" ); + HBLog( "HBAudioInit: calloc() failed, gonna crash" ); return NULL; } a->id = id; a->language = strdup( language ); - a->inSampleRate = 0; - a->outSampleRate = 44100; - a->delay = 0; - a->ac3Fifo = NULL; - a->rawFifo = NULL; - a->mp3Fifo = NULL; - a->ac3Dec = NULL; - a->mp3Enc = NULL; - + a->start = -1; + return a; } void HBAudioClose( HBAudio ** _a ) { HBAudio * a = *_a; - + free( a->language ); free( a ); diff --git a/core/Utils.h b/core/Utils.h index ba1a9101e..a83c36c65 100644 --- a/core/Utils.h +++ b/core/Utils.h @@ -1,4 +1,4 @@ -/* $Id: Utils.h,v 1.6 2003/11/07 21:22:17 titer Exp $ +/* $Id: Utils.h,v 1.22 2004/01/21 18:40:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -14,7 +14,7 @@ #include <unistd.h> #include <inttypes.h> typedef uint8_t byte_t; -#ifdef SYS_BEOS +#ifdef HB_BEOS # include <OS.h> #endif @@ -35,27 +35,33 @@ typedef uint8_t byte_t; #define VOUT_ASPECT_FACTOR 432000 #endif -typedef struct HBAc3Dec HBAc3Dec; +typedef struct HBHandle HBHandle; + +/* Utils */ typedef struct HBAudio HBAudio; -typedef struct HBAviMux HBAviMux; typedef struct HBBuffer HBBuffer; -typedef struct HBDVDRead HBDVDRead; +typedef struct HBCond HBCond; typedef struct HBFifo HBFifo; typedef struct HBList HBList; typedef struct HBLock HBLock; -typedef struct HBHandle HBHandle; -typedef struct HBMp3Enc HBMp3Enc; -typedef struct HBMpeg2Dec HBMpeg2Dec; -typedef struct HBFfmpegEnc HBFfmpegEnc; -typedef struct HBMadDec HBMadDec; -typedef struct HBScale HBScale; -typedef struct HBScan HBScan; -typedef struct HBStatus HBStatus; -typedef struct HBThread HBThread; typedef struct HBTitle HBTitle; +typedef struct HBThread HBThread; + +/* (De)Muxers */ +typedef struct HBAviMux HBAviMux; +typedef struct HBOgmMux HBOgmMux; +typedef struct HBDVDRead HBDVDRead; +typedef struct HBMp4Mux HBMp4Mux; +typedef struct HBScan HBScan; + typedef struct HBWork HBWork; typedef struct HBWorkThread HBWorkThread; -typedef struct HBXvidEnc HBXvidEnc; + +/* AVI stuff */ +typedef struct HBAviMainHeader HBAviMainHeader; +typedef struct HBAviStreamHeader HBAviStreamHeader; +typedef struct HBBitmapInfo HBBitmapInfo; +typedef struct HBWaveFormatEx HBWaveFormatEx; /* Misc functions which may be used from anywhere */ void HBSnooze( int time ); @@ -65,7 +71,7 @@ int HBPStoES( HBBuffer ** psBuffer, HBList * esBufferList ); /* HBList functions */ HBList * HBListInit(); -int HBListCountItems( HBList * ); +int HBListCount( HBList * ); void HBListAdd( HBList *, void * item ); void HBListRemove( HBList *, void * item ); void * HBListItemAt( HBList *, int index ); @@ -79,135 +85,143 @@ void HBTitleClose( HBTitle ** ); HBAudio * HBAudioInit( int id, char * language ); void HBAudioClose( HBAudio ** ); -/* Possible states */ -typedef enum -{ - HB_MODE_UNDEF = 00000, - HB_MODE_NEED_DEVICE = 00001, - HB_MODE_SCANNING = 00002, - HB_MODE_INVALID_DEVICE = 00004, - HB_MODE_READY_TO_RIP = 00010, - HB_MODE_ENCODING = 00020, - HB_MODE_PAUSED = 00040, - HB_MODE_STOPPING = 00100, - HB_MODE_DONE = 00200, - HB_MODE_CANCELED = 00400, - HB_MODE_ERROR = 01000, - HB_MODE_EXITING = 02000 -} 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; +#define HB_SUCCESS 0x00 +#define HB_CANCELED 0x01 +#define HB_ERROR_A52_SYNC 0x02 +#define HB_ERROR_AVI_WRITE 0x04 +#define HB_ERROR_DVD_OPEN 0x08 +#define HB_ERROR_DVD_READ 0x10 +#define HB_ERROR_MP3_INIT 0x20 +#define HB_ERROR_MP3_ENCODE 0x40 +#define HB_ERROR_MPEG4_INIT 0x80 /* Possible codecs */ -typedef enum -{ - HB_CODEC_FFMPEG = 0, - HB_CODEC_XVID -} HBCodec; +#define HB_CODEC_MPEG2 0x00 +#define HB_CODEC_FFMPEG 0x01 +#define HB_CODEC_XVID 0x02 +#define HB_CODEC_AC3 0x04 +#define HB_CODEC_MP3 0x08 +#define HB_CODEC_AAC 0x10 +#define HB_CODEC_X264 0x20 +#define HB_CODEC_VORBIS 0x40 + +/* Possible muxers */ +#define HB_MUX_AVI 0x00 +#define HB_MUX_MP4 0x01 +#define HB_MUX_OGM 0x02 -struct HBStatus +struct HBTitle { - HBMode mode; - - /* HB_MODE_SCANNING */ - int scannedTitle; + /* DVD info */ + char * device; + int index; + int length; - /* HB_MODE_SCANDONE */ - HBList * titleList; - - /* HB_MODE_ENCODING || HB_MODE_PAUSED */ - float position; - int pass; - int passCount; - float frameRate; - float avFrameRate; - uint32_t remainingTime; /* in seconds */ + /* Audio infos */ + HBList * audioList; + HBList * ripAudioList; - /* HB_MODE_ERROR */ - HBError error; -}; - -struct HBTitle -{ - char * device; - int index; - int length; - char * file; + /* See DVDRead.c */ + int64_t start; /* Video input */ - int inWidth; - int inHeight; - int aspect; - int rate; - int rateBase; + int inWidth; + int inHeight; + int aspect; + int rate; + int rateBase; /* Video output */ - int outWidth; - int outHeight; - int outWidthMax; - int outHeightMax; - int topCrop; - int bottomCrop; - int leftCrop; - int rightCrop; - int deinterlace; - HBCodec codec; - int bitrate; - int twoPass; - - /* Audio infos */ - HBList * audioList; + int outWidth; + int outHeight; + int outWidthMax; + int outHeightMax; + int topCrop; + int bottomCrop; + int leftCrop; + int rightCrop; + int deinterlace; + int autoTopCrop; + int autoBottomCrop; + int autoLeftCrop; + int autoRightCrop; + + /* Encoder settings */ + int codec; + int bitrate; + int twoPass; + + /* Muxer settings */ + char * file; + int mux; + + /* MP4 muxer specific */ + int track; + uint8_t * esConfig; + int esConfigLength; + + /* AVI muxer specific */ + HBAviMainHeader * aviMainHeader; + HBAviStreamHeader * aviVideoHeader; + HBBitmapInfo * aviVideoFormat; /* Fifos */ - HBFifo * mpeg2Fifo; - HBFifo * rawFifo; - HBFifo * scaledFifo; - HBFifo * mpeg4Fifo; + HBFifo * inFifo; + HBFifo * rawFifo; + HBFifo * scaledFifo; + HBFifo * outFifo; /* Threads */ HBDVDRead * dvdRead; - HBMpeg2Dec * mpeg2Dec; - HBScale * scale; - HBFfmpegEnc * ffmpegEnc; - HBXvidEnc * xvidEnc; HBAviMux * aviMux; + HBMp4Mux * mp4Mux; + HBOgmMux * ogmMux; HBWorkThread * workThreads[8]; + + /* Work objects */ + HBWork * decoder; + HBWork * scale; + HBWork * encoder; }; struct HBAudio { - /* Ident */ - uint32_t id; - char * language; - - /* Settings */ - int inSampleRate; - int outSampleRate; - int inBitrate; - int outBitrate; - - int delay; /* in ms */ - - /* Fifos */ - HBFifo * ac3Fifo; - HBFifo * rawFifo; - HBFifo * mp3Fifo; - - /* Threads */ - HBAc3Dec * ac3Dec; - HBMp3Enc * mp3Enc; -}; + /* Ident */ + uint32_t id; + char * language; + + /* Settings */ + int codec; + int inSampleRate; + int outSampleRate; + int inBitrate; + int outBitrate; + + int delay; /* in ms */ + + /* See DVDRead.c */ + int64_t start; + + /* MPEG-4 config, used in the MP4 muxer */ + uint8_t * esConfig; + unsigned long esConfigLength; + /* MP4 track id */ + int track; + /* AVI stuff */ + uint32_t aviFourCC; + HBAviStreamHeader * aviAudioHeader; + HBWaveFormatEx * aviAudioFormat; + + /* Fifos */ + HBFifo * inFifo; + HBFifo * rawFifo; + HBFifo * outFifo; + + /* Work objects */ + HBWork * decoder; + HBWork * encoder;; +}; #endif diff --git a/core/VorbisEnc.c b/core/VorbisEnc.c new file mode 100644 index 000000000..a4f305720 --- /dev/null +++ b/core/VorbisEnc.c @@ -0,0 +1,257 @@ +/* $Id: VorbisEnc.c,v 1.4 2003/12/26 20:03:27 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "HBInternal.h" + +/* libvorbis */ +#include <vorbis/vorbisenc.h> + +#define OGGVORBIS_FRAME_SIZE 1024 + +typedef struct HBVorbisEnc +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBAudio * audio; + + int inited; + vorbis_info vi; + vorbis_comment vc; + vorbis_dsp_state vd; + vorbis_block vb; + + HBBuffer *rawBuffer; + int rawBufferPos; /* in bytes */ + float position; + int32_t * inputBuffer; + unsigned long samplesGot; + unsigned long inputSamples; + + HBBuffer *vorbisBuffer; + + HBBuffer *header[3]; +} HBVorbisEnc; + +/* Local prototypes */ +static int VorbisEncWork( HBWork * ); +static int GetSamples( HBVorbisEnc * ); + +HBWork *HBVorbisEncInit ( HBHandle *handle, HBAudio *audio ) +{ + HBVorbisEnc *enc = malloc( sizeof( HBVorbisEnc ) ); + + enc->name = strdup( "VorbisEnc" ); + enc->work = VorbisEncWork; + + enc->handle = handle; + enc->audio = audio; + + enc->inited = 0; + enc->rawBuffer = NULL; + enc->inputSamples = 2 * OGGVORBIS_FRAME_SIZE; + enc->inputBuffer = malloc( 2 * OGGVORBIS_FRAME_SIZE * sizeof( int32_t ) ); + enc->samplesGot = 0; + + enc->vorbisBuffer = NULL; + + return (HBWork*) enc; +} + +void HBVorbisEncClose( HBWork **_enc ) +{ + HBVorbisEnc *enc = (HBVorbisEnc*) *_enc; + + if( enc->inited ) + { + vorbis_block_clear( &enc->vb ); + vorbis_dsp_clear( &enc->vd ); + vorbis_comment_clear( &enc->vc ); + vorbis_info_clear( &enc->vi ); + } + + free( enc->name ); + free( enc ); + + *_enc = NULL; +} + +static HBBuffer *PacketToBuffer( ogg_packet *op ) +{ + HBBuffer *buf = HBBufferInit( sizeof( ogg_packet ) + op->bytes ); + + memcpy( buf->data, op, sizeof( ogg_packet ) ); + memcpy( buf->data + sizeof( ogg_packet ), op->packet, op->bytes ); + + return buf; +} + +static int VorbisEncWork( HBWork *w ) +{ + HBVorbisEnc *enc = (HBVorbisEnc*)w; + HBAudio *audio = enc->audio; + int didSomething = 0; + + float **buffer; + int i; + + + if( !enc->inited ) + { + ogg_packet header[3]; + + /* Get a first buffer so we know that audio->inSampleRate is correct */ + if( ( enc->rawBuffer = HBFifoPop( audio->rawFifo ) ) == NULL ) + { + return 0; + } + enc->inited = 1; + + didSomething = 1; + enc->rawBufferPos = 0; + enc->position = enc->rawBuffer->position; + + /* No resampling */ + audio->outSampleRate = audio->inSampleRate; + + /* init */ + vorbis_info_init( &enc->vi ); + if( vorbis_encode_setup_vbr( &enc->vi, 2 /* channel */, audio->inSampleRate, 1.0/* quality 0.0 -> 1.0*/ ) ) + { + HBLog( "VorbisEnc: vorbis_encode_setup_vbr failed" ); + return 0; + } + vorbis_encode_setup_init( &enc->vi ); + + /* add a comment */ + vorbis_comment_init( &enc->vc ); + vorbis_comment_add_tag( &enc->vc, "ENCODER", "Handbrake"); + + /* set up the analysis state and auxiliary encoding storage */ + vorbis_analysis_init( &enc->vd, &enc->vi); + vorbis_block_init( &enc->vd, &enc->vb); + + + /* get the 3 headers */ + vorbis_analysis_headerout( &enc->vd, &enc->vc, + &header[0], &header[1], &header[2] ); + + enc->header[0] = PacketToBuffer( &header[0] ); + enc->header[1] = PacketToBuffer( &header[1] ); + enc->header[2] = PacketToBuffer( &header[2] ); + } + + if( enc->header[0] ) + { + HBLog( "VorbisEncWork: sending header 1" ); + if( !HBFifoPush( audio->outFifo, &enc->header[0] ) ) + { + return didSomething; + } + didSomething = 1; + } + if( enc->header[1] ) + { + HBLog( "VorbisEncWork: sending header 2" ); + if( !HBFifoPush( audio->outFifo, &enc->header[1] ) ) + { + return didSomething; + } + didSomething = 1; + } + if( enc->header[2] ) + { + HBLog( "VorbisEncWork: sending header 3" ); + if( !HBFifoPush( audio->outFifo, &enc->header[2] ) ) + { + return didSomething; + } + didSomething = 1; + } + + /* Push already encoded data */ + if( enc->vorbisBuffer ) + { + if( !HBFifoPush( audio->outFifo, &enc->vorbisBuffer ) ) + { + return didSomething; + } + } + + /* Try to extract more data */ + if( vorbis_analysis_blockout( &enc->vd, &enc->vb ) == 1 ) + { + ogg_packet op; + + vorbis_analysis( &enc->vb, NULL ); + vorbis_bitrate_addblock( &enc->vb ); + + if( vorbis_bitrate_flushpacket( &enc->vd, &op ) ) + { + enc->vorbisBuffer = PacketToBuffer( &op ); + enc->vorbisBuffer->position = enc->position; + return 1; + } + } + + didSomething = 1; + + /* FUCK -Werror ! */ + if( !GetSamples( enc ) ) + { + return didSomething; + } + + buffer = vorbis_analysis_buffer( &enc->vd, OGGVORBIS_FRAME_SIZE ); + for( i = 0; i < OGGVORBIS_FRAME_SIZE; i++ ) + { + buffer[0][i] = (float)enc->inputBuffer[2 * i + 0]/32768.f; + buffer[1][i] = (float)enc->inputBuffer[2 * i + 1]/32768.f; + } + vorbis_analysis_wrote( &enc->vd, OGGVORBIS_FRAME_SIZE ); + + enc->samplesGot = 0; + + return 1; +} + +static int GetSamples( HBVorbisEnc * f ) +{ + while( f->samplesGot < f->inputSamples ) + { + int i, copy; + + if( !f->rawBuffer ) + { + if( !( f->rawBuffer = HBFifoPop( f->audio->rawFifo ) ) ) + { + return 0; + } + + f->rawBufferPos = 0; + f->position = f->rawBuffer->position; + } + + copy = MIN( f->inputSamples - f->samplesGot, + ( f->rawBuffer->samples - f->rawBufferPos ) * 2 ); + + for( i = 0; i < copy; i += 2 ) + { + f->inputBuffer[f->samplesGot++] = + f->rawBuffer->left[f->rawBufferPos]; + f->inputBuffer[f->samplesGot++] = + f->rawBuffer->right[f->rawBufferPos]; + f->rawBufferPos++; + } + + if( f->rawBufferPos == f->rawBuffer->samples ) + { + HBBufferClose( &f->rawBuffer ); + } + } + + return 1; +} diff --git a/core/Work.c b/core/Work.c index b15e50839..f2f05030a 100644 --- a/core/Work.c +++ b/core/Work.c @@ -1,11 +1,10 @@ -/* $Id: Work.c,v 1.4 2003/11/06 12:33:11 titer Exp $ +/* $Id: Work.c,v 1.12 2004/01/05 16:50:25 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "Thread.h" -#include "Work.h" +#include "HBInternal.h" /* Local prototypes */ static void WorkThread( void * t ); @@ -17,22 +16,22 @@ struct HBWork struct HBWorkThread { - HBHandle * handle; + HBHandle * handle; - HBList * workList; - int firstThread; + HBList * workList; + int firstThread; - int die; - HBThread * thread; + volatile int die; + HBThread * thread; }; HBWorkThread * HBWorkThreadInit( HBHandle * handle, HBTitle * title, - HBAudio * audio, HBAudio * optAudio, int firstThread ) { int i; - HBWork * w; - + HBWork * w; + HBAudio * audio; + HBWorkThread * t; if( !( t = malloc( sizeof( HBWorkThread ) ) ) ) { @@ -44,22 +43,17 @@ HBWorkThread * HBWorkThreadInit( HBHandle * handle, HBTitle * title, /* Build a list of work objects. They all include HB_WORK_COMMON_MEMBERS, so we'll be able to do the job without - knowing what each one actually do */ + knowing what each one actually does */ t->workList = HBListInit(); - HBListAdd( t->workList, title->mpeg2Dec ); + HBListAdd( t->workList, title->decoder ); HBListAdd( t->workList, title->scale ); + HBListAdd( t->workList, title->encoder ); - if( title->codec == HB_CODEC_FFMPEG ) - HBListAdd( t->workList, title->ffmpegEnc ); - else if( title->codec == HB_CODEC_XVID ) - HBListAdd( t->workList, title->xvidEnc ); - - HBListAdd( t->workList, audio->ac3Dec ); - HBListAdd( t->workList, audio->mp3Enc ); - if( optAudio ) + for( i = 0; i < HBListCount( title->ripAudioList ); i++ ) { - HBListAdd( t->workList, optAudio->ac3Dec ); - HBListAdd( t->workList, optAudio->mp3Enc ); + audio = HBListItemAt( title->ripAudioList, i ); + HBListAdd( t->workList, audio->decoder ); + HBListAdd( t->workList, audio->encoder ); } t->firstThread = firstThread; @@ -69,7 +63,7 @@ HBWorkThread * HBWorkThreadInit( HBHandle * handle, HBTitle * title, is done by the first worker thread (see HBStartRip) */ if( t->firstThread ) { - for( i = 0; i < HBListCountItems( t->workList ); i++ ) + for( i = 0; i < HBListCount( t->workList ); i++ ) { w = (HBWork*) HBListItemAt( t->workList, i ); w->lock = HBLockInit(); @@ -100,15 +94,15 @@ void HBWorkThreadClose( HBWorkThread ** _t ) { int i; uint64_t total = 0; - - for( i = 0; i < HBListCountItems( t->workList ); i++ ) + + for( i = 0; i < HBListCount( t->workList ); i++ ) { w = (HBWork*) HBListItemAt( t->workList, i ); HBLockClose( &w->lock ); total += w->time; } - for( i = 0; i < HBListCountItems( t->workList ); i++ ) + for( i = 0; i < HBListCount( t->workList ); i++ ) { w = (HBWork*) HBListItemAt( t->workList, i ); HBLog( "HBWorkThreadClose: %- 9s = %05.2f %%", w->name, @@ -116,12 +110,12 @@ void HBWorkThreadClose( HBWorkThread ** _t ) } } - + /* Free memory */ HBListClose( &t->workList ); free( t ); - (*_t) = NULL; + *_t = NULL; } static void WorkThread( void * _t ) @@ -131,57 +125,51 @@ static void WorkThread( void * _t ) int didSomething, i; uint64_t date; - for( ;; ) + didSomething = 0; + + for( i = 0; !t->die; i++ ) { HBCheckPaused( t->handle ); - - didSomething = 0; - for( i = 0; i < HBListCountItems( t->workList ); i++ ) + if( i == HBListCount( t->workList ) ) { - if( t->die ) + /* If nothing could be done, wait a bit to prevent a useless + CPU-consuming loop */ + if( !didSomething ) { - break; + HBSnooze( 5000 ); } - - w = (HBWork*) HBListItemAt( t->workList, i ); + didSomething = 0; + i = 0; + } - /* Check if another thread isn't using this work object. - If not, lock it */ - HBLockLock( w->lock ); - if( w->used ) - { - HBLockUnlock( w->lock ); - continue; - } - w->used = 1; - HBLockUnlock( w->lock ); - - /* Actually do the job */ - date = HBGetDate(); - if( w->work( w ) ) - { - w->time += HBGetDate() - date; - didSomething = 1; - } + w = (HBWork*) HBListItemAt( t->workList, i ); - /* Unlock */ - HBLockLock( w->lock ); - w->used = 0; + /* Check if another thread isn't using this work object */ + HBLockLock( w->lock ); + if( w->used ) + { + /* It's in use. Forget about this one and try the next + one */ HBLockUnlock( w->lock ); + continue; } + /* It's unused, lock it */ + w->used = 1; + HBLockUnlock( w->lock ); - if( t->die ) + /* Do the job */ + date = HBGetDate(); + if( w->work( w ) ) { - break; + w->time += HBGetDate() - date; + didSomething = 1; } - /* If nothing could be done, wait a bit to prevent a useless - CPU-consuming loop */ - if( !didSomething ) - { - HBSnooze( 10000 ); - } + /* Unlock it */ + HBLockLock( w->lock ); + w->used = 0; + HBLockUnlock( w->lock ); } } diff --git a/core/Work.h b/core/Work.h index 8d3cfba15..b764e1160 100644 --- a/core/Work.h +++ b/core/Work.h @@ -1,4 +1,4 @@ -/* $Id: Work.h,v 1.1 2003/11/03 12:08:01 titer Exp $ +/* $Id: Work.h,v 1.4 2003/12/26 20:03:27 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -7,8 +7,6 @@ #ifndef HB_WORK_H #define HB_WORK_H -#include "HandBrakeInternal.h" - #define HB_WORK_COMMON_MEMBERS \ char * name; \ HBLock * lock; \ @@ -16,12 +14,8 @@ uint64_t time; \ int (*work) ( HBWork * ); -void HBWorkLock( HBWork * ); -void HBWorkWork( HBWork * ); -void HBWorkUnlock( HBWork * ); - -HBWorkThread * HBWorkThreadInit( HBHandle *, HBTitle *, HBAudio *, - HBAudio *, int firstThread ); +HBWorkThread * HBWorkThreadInit( HBHandle *, HBTitle *, + int firstThread ); void HBWorkThreadClose( HBWorkThread ** ); #endif diff --git a/core/X264Enc.c b/core/X264Enc.c new file mode 100644 index 000000000..50b9ab8bf --- /dev/null +++ b/core/X264Enc.c @@ -0,0 +1,167 @@ +/* $Id: X264Enc.c,v 1.3 2003/12/26 20:03:27 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "HBInternal.h" + +/* x264 */ +#include "x264.h" + +typedef struct HBX264Enc +{ + HB_WORK_COMMON_MEMBERS + + HBHandle *handle; + HBTitle *title; + + HBBuffer *buffer; + + x264_t *h; + x264_picture_t picture; +} HBX264Enc; + +/* Local prototypes */ +static int HBX264EncWork( HBWork * ); + +HBWork *HBX264EncInit( HBHandle * handle, HBTitle * title ) +{ + HBX264Enc *f = malloc( sizeof( HBX264Enc ) ); + + if( f ) + { + x264_param_t param; + + f->name = strdup( "X264Enc" ); + f->work = HBX264EncWork; + + f->handle = handle; + f->title = title; + + f->buffer = NULL; + + x264_param_default( ¶m ); + + param.i_width = title->outWidth; + param.i_height= title->outHeight; + param.i_iframe = 5 * title->rate / title->rateBase; + /* FIXME */ + param.b_deblocking_filter = 0; + param.i_me = 1; + + if( ( f->h = x264_encoder_open( ¶m ) ) == NULL ) + { + HBLog( "x264: x264_encoder_new failed" ); + return NULL; + } + memset( &f->picture, 0, sizeof( x264_picture_t ) ); + f->picture.i_width = param.i_width; + f->picture.i_height = param.i_height; + f->picture.i_plane = 3; + + HBLog( "x264: opening with %dx%d iframes=%d", param.i_width, param.i_height, param.i_iframe ); + } + + return (HBWork*) f; +} + +void HBX264EncClose( HBWork **_f ) +{ + HBX264Enc *f = (HBX264Enc*) *_f; + + x264_encoder_close( f->h ); + + if( f->buffer ) + { + HBBufferClose( &f->buffer ); + } + + free( f->name ); + + free( f ); + + *_f = NULL; +} + +/* TODO trash buffer->pass == 1 + * return 0 ->rien fait + * 1 -> sinon + */ +static int HBX264EncWork( HBWork * w ) +{ + HBX264Enc * f = (HBX264Enc*) w; + HBTitle * title = f->title; + + HBBuffer * frame; + int didSomething = 0; + + x264_nal_t *nal; + int i_nal; + int i; + + if( f->buffer ) + { + if( !HBFifoPush( title->outFifo, &f->buffer ) ) + { + /* nothing done */ + return 0; + } + didSomething = 1; + } + + if( ( frame = HBFifoPop( title->scaledFifo ) ) == NULL ) + { + return didSomething; + } + + if( frame->pass == 1 ) + { + /* Trash all first pass buffer */ + HBBufferClose( &frame ); + return 1; + } + + f->picture.i_stride[0] = title->outWidth; + f->picture.i_stride[1] = title->outWidth/2; + f->picture.i_stride[2] = title->outWidth/2; + + f->picture.plane[0] = frame->data; + f->picture.plane[1] = &f->picture.plane[0][title->outWidth*title->outHeight]; + f->picture.plane[2] = &f->picture.plane[1][title->outWidth*title->outHeight/4]; + + x264_encoder_encode( f->h, &nal, &i_nal, &f->picture ); + + f->buffer = HBBufferInit( 3 * title->outWidth * title->outHeight / 2 ); /* FIXME */ + f->buffer->keyFrame = 0; + f->buffer->position = frame->position; + f->buffer->size = 0; + + for( i = 0; i < i_nal; i++ ) + { + int i_data = f->buffer->alloc - f->buffer->size; + int i_size; + + i_size = x264_nal_encode( &f->buffer->data[f->buffer->size], + &i_data, 1, &nal[i] ); + if( i_size <= 0 ) + { + fprintf( stderr, "#################### error" ); + } + + f->buffer->size += i_size; + + if( nal[i].i_ref_idc == NAL_PRIORITY_HIGH || + nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST ) + { + f->buffer->keyFrame = 1; + } + } + + /* Inform the GUI about the current position */ + HBPosition( f->handle, frame->position ); + + HBBufferClose( &frame ); + + return 1; +} diff --git a/core/XvidEnc.c b/core/XvidEnc.c index 2ca6bca6f..fe9e8ddbc 100644 --- a/core/XvidEnc.c +++ b/core/XvidEnc.c @@ -1,34 +1,33 @@ -/* $Id: XvidEnc.c,v 1.7 2003/11/09 21:26:52 titer Exp $ +/* $Id: XvidEnc.c,v 1.18 2004/01/08 22:02:29 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "Fifo.h" -#include "Work.h" -#include "XvidEnc.h" -#include "XvidVbr.h" +#include "HBInternal.h" -#include <xvid.h> +#include "xvid.h" -/* Local prototypes */ -static int XvidEncWork( HBWork * ); - -struct HBXvidEnc +typedef struct HBXvidEnc { HB_WORK_COMMON_MEMBERS HBHandle * handle; HBTitle * title; + char file[1024]; void * xvid; - vbr_control_t xvidVbr; - XVID_ENC_FRAME frame; + xvid_enc_frame_t frame; HBBuffer * mpeg4Buffer; int pass; -}; + int frames; + int64_t bytes; +} HBXvidEnc; + +/* Local prototypes */ +static int XvidEncWork( HBWork * ); -HBXvidEnc * HBXvidEncInit( HBHandle * handle, HBTitle * title ) +HBWork * HBXvidEncInit( HBHandle * handle, HBTitle * title ) { HBXvidEnc * x; if( !( x = malloc( sizeof( HBXvidEnc ) ) ) ) @@ -43,38 +42,53 @@ HBXvidEnc * HBXvidEncInit( HBHandle * handle, HBTitle * title ) x->handle = handle; x->title = title; - x->xvid = NULL; - - x->frame.general = XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V; - x->frame.motion = PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | - PMV_EXTSEARCH16 | PMV_EARLYSTOP8 | - PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8 | - PMV_USESQUARES16; - - x->frame.colorspace = XVID_CSP_I420; - - x->frame.quant_intra_matrix = NULL; - x->frame.quant_inter_matrix = NULL; + memset( x->file, 0, 1024 ); + snprintf( x->file, 1023, "/tmp/HB.%d.xvid.log", + HBGetPid( x->handle ) ); + x->xvid = NULL; x->mpeg4Buffer = NULL; x->pass = 42; + x->frames = 0; + x->bytes = 0; - return x; + return (HBWork*) x; } -void HBXvidEncClose( HBXvidEnc ** _x ) +void HBXvidEncClose( HBWork ** _x ) { - HBXvidEnc * x = *_x; + HBXvidEnc * x = (HBXvidEnc*) *_x; if( x->xvid ) { HBLog( "HBXvidEnc: closing libxvidcore (pass %d)", x->pass ); - xvid_encore( x->xvid, XVID_ENC_DESTROY, NULL, NULL); - vbrFinish( &x->xvidVbr ); } - + if( x->frames ) + { + float bitrate = (float) x->bytes * x->title->rate / x->frames / + x->title->rateBase / 128; + int64_t bytes = (int64_t) x->frames * x->title->bitrate * 128 * + x->title->rateBase / x->title->rate; + + HBLog( "HBXvidEnc: %d frames encoded (%lld bytes), %.2f kbps", + x->frames, x->bytes, bitrate ); + + if( x->bytes > bytes ) + { + HBLog( "HBXvidEnc: %lld more bytes than expected " + "(error=%.2f %%)", x->bytes - bytes, + 100.0 * ( x->bytes - bytes ) / bytes ); + } + else if( x->bytes < bytes ) + { + HBLog( "HBXvidEnc: %lld less bytes than expected " + "(error=%.2f %%)", bytes - x->bytes, + 100.0 * ( bytes - x->bytes ) / bytes ); + } + } + free( x->name ); free( x ); *_x = NULL; @@ -86,13 +100,12 @@ static int XvidEncWork( HBWork * w ) HBTitle * title = x->title; HBBuffer * scaledBuffer; HBBuffer * mpeg4Buffer; - XVID_ENC_STATS stats; int didSomething = 0; if( x->mpeg4Buffer ) { - if( HBFifoPush( title->mpeg4Fifo, &x->mpeg4Buffer ) ) + if( HBFifoPush( title->outFifo, &x->mpeg4Buffer ) ) { didSomething = 1; } @@ -114,8 +127,12 @@ static int XvidEncWork( HBWork * w ) /* Init or re-init if needed */ if( scaledBuffer->pass != x->pass ) { - XVID_INIT_PARAM xinit; - XVID_ENC_PARAM xparam; + xvid_gbl_init_t xvid_gbl_init; + xvid_enc_create_t xvid_enc_create; + xvid_plugin_single_t single; + xvid_plugin_2pass1_t rc2pass1; + xvid_plugin_2pass2_t rc2pass2; + xvid_enc_plugin_t plugins[7]; if( x->xvid ) { @@ -123,89 +140,93 @@ static int XvidEncWork( HBWork * w ) x->pass ); xvid_encore( x->xvid, XVID_ENC_DESTROY, NULL, NULL); - vbrFinish( &x->xvidVbr ); } x->pass = scaledBuffer->pass;; - HBLog( "HBXvidEnc: opening libxvidcore (pass %d)", x->pass ); - xinit.cpu_flags = 0; - xvid_init( NULL, 0, &xinit, NULL ); + memset( &xvid_gbl_init, 0, sizeof( xvid_gbl_init ) ); + xvid_gbl_init.version = XVID_VERSION; + xvid_global( NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL ); - xparam.width = title->outWidth; - xparam.height = title->outHeight; + memset(&xvid_enc_create, 0, sizeof(xvid_enc_create)); + xvid_enc_create.version = XVID_VERSION; + xvid_enc_create.width = title->outWidth; + xvid_enc_create.height = title->outHeight; + xvid_enc_create.zones = NULL; + xvid_enc_create.num_zones = 0; + xvid_enc_create.plugins = plugins; + xvid_enc_create.num_plugins = 0; - xparam.fincr = title->rateBase; - xparam.fbase = title->rate; - - xparam.rc_bitrate = title->bitrate * 1024; - - /* Default values should be ok */ - xparam.rc_reaction_delay_factor = -1; - xparam.rc_averaging_period = -1; - xparam.rc_buffer = -1; - xparam.max_quantizer = -1; - xparam.min_quantizer = -1; - xparam.max_key_interval = -1; - - if( xvid_encore( NULL, XVID_ENC_CREATE, &xparam, NULL ) ) - { - HBLog( "HBXvidEnc: xvid_encore() failed" ); - } - - x->xvid = xparam.handle; - - /* Init VBR engine */ - vbrSetDefaults( &x->xvidVbr ); if( !x->pass ) { - x->xvidVbr.mode = VBR_MODE_1PASS; + memset( &single, 0, sizeof( single ) ); + single.version = XVID_VERSION; + single.bitrate = 1024 * title->bitrate; + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single; + plugins[xvid_enc_create.num_plugins].param = &single; + xvid_enc_create.num_plugins++; } else if( x->pass == 1 ) { - x->xvidVbr.mode = VBR_MODE_2PASS_1; + memset( &rc2pass1, 0, sizeof( rc2pass1 ) ); + rc2pass1.version = XVID_VERSION; + rc2pass1.filename = x->file; + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass1; + plugins[xvid_enc_create.num_plugins].param = &rc2pass1; + xvid_enc_create.num_plugins++; } - else + else if( x->pass == 2 ) { - x->xvidVbr.mode = VBR_MODE_2PASS_2; + memset(&rc2pass2, 0, sizeof(xvid_plugin_2pass2_t)); + rc2pass2.version = XVID_VERSION; + rc2pass2.filename = x->file; + rc2pass2.bitrate = 1024 * title->bitrate; + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2; + plugins[xvid_enc_create.num_plugins].param = &rc2pass2; + xvid_enc_create.num_plugins++; } - x->xvidVbr.fps = (double) title->rate / title->rateBase; - x->xvidVbr.debug = 0; - x->xvidVbr.filename = malloc( 1024 ); - memset( x->xvidVbr.filename, 0, 1024 ); - snprintf( x->xvidVbr.filename, 1023, "/tmp/HB.%d.xvid.log", - HBGetPid( x->handle ) ); - x->xvidVbr.desired_bitrate = title->bitrate * 1024; - x->xvidVbr.max_key_interval = 10 * title->rate / title->rateBase; - - vbrInit( &x->xvidVbr ); + + xvid_enc_create.num_threads = 0; + xvid_enc_create.fincr = title->rateBase; + xvid_enc_create.fbase = title->rate; + xvid_enc_create.max_key_interval = 10 * title->rate / title->rateBase; + xvid_enc_create.max_bframes = 0; + xvid_enc_create.bquant_ratio = 150; + xvid_enc_create.bquant_offset = 100; + xvid_enc_create.frame_drop_ratio = 0; + xvid_enc_create.global = 0; + + xvid_encore( NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL ); + x->xvid = xvid_enc_create.handle; } mpeg4Buffer = HBBufferInit( title->outWidth * title->outHeight * 3 / 2 ); mpeg4Buffer->position = scaledBuffer->position; + memset( &x->frame, 0, sizeof( x->frame ) ); + x->frame.version = XVID_VERSION; x->frame.bitstream = mpeg4Buffer->data; - x->frame.length = -1; - - x->frame.image = scaledBuffer->data; - - x->frame.quant = vbrGetQuant( &x->xvidVbr ); - x->frame.intra = vbrGetIntra( &x->xvidVbr ); - - x->frame.hint.hintstream = NULL; - - if( xvid_encore( x->xvid, XVID_ENC_ENCODE, &x->frame, &stats ) ) - { - HBLog( "HBXvidEnc: xvid_encore() failed" ); - } - - vbrUpdate( &x->xvidVbr, stats.quant, x->frame.intra, stats.hlength, - x->frame.length, stats.kblks, stats.mblks, stats.ublks ); + x->frame.length = -1; + x->frame.input.plane[0] = scaledBuffer->data; + x->frame.input.csp = XVID_CSP_I420; + x->frame.input.stride[0] = title->outWidth; + x->frame.vol_flags = 0; + x->frame.vop_flags = XVID_VOP_HALFPEL | XVID_VOP_INTER4V | + XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED; + x->frame.type = XVID_TYPE_AUTO; + x->frame.quant = 0; + x->frame.motion = XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | + XVID_ME_EXTSEARCH16 | XVID_ME_ADVANCEDDIAMOND8 | + XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 | + XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP; + x->frame.quant_intra_matrix = NULL; + x->frame.quant_inter_matrix = NULL; - mpeg4Buffer->size = x->frame.length; - mpeg4Buffer->keyFrame = x->frame.intra; + mpeg4Buffer->size = xvid_encore( x->xvid, XVID_ENC_ENCODE, + &x->frame, NULL ); + mpeg4Buffer->keyFrame = ( x->frame.out_flags & XVID_KEYFRAME ); /* Inform the GUI about the current position */ HBPosition( x->handle, scaledBuffer->position ); @@ -217,8 +238,20 @@ static int XvidEncWork( HBWork * w ) HBBufferClose( &mpeg4Buffer ); return didSomething; } + else + { + if( !title->esConfig ) + { + /* KLUDGE */ + title->esConfig = malloc( 15 ); + title->esConfigLength = 15; + memcpy( title->esConfig, mpeg4Buffer->data + 4, 15 ); + } + x->frames++; + x->bytes += mpeg4Buffer->size; + x->mpeg4Buffer = mpeg4Buffer; + } - x->mpeg4Buffer = mpeg4Buffer; return didSomething; } diff --git a/core/XvidEnc.h b/core/XvidEnc.h deleted file mode 100644 index 01cb6f4d4..000000000 --- a/core/XvidEnc.h +++ /dev/null @@ -1,15 +0,0 @@ -/* $Id: XvidEnc.h,v 1.1 2003/11/03 12:08:01 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://handbrake.m0k.org/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_XVID_ENC_H -#define HB_XVID_ENC_H - -#include "HandBrakeInternal.h" - -HBXvidEnc * HBXvidEncInit( HBHandle *, HBTitle * ); -void HBXvidEncClose( HBXvidEnc ** ); - -#endif diff --git a/core/XvidVbr.c b/core/XvidVbr.c deleted file mode 100644 index ce66c3769..000000000 --- a/core/XvidVbr.c +++ /dev/null @@ -1,1648 +0,0 @@ -/****************************************************************************** - * - * XviD VBR Library - * - * Copyright (C) 2002 Edouard Gomez <[email protected]> - * - * The curve treatment algorithm is based on work done by Foxer <email?> and - * Dirk Knop <[email protected]> for the XviD vfw dynamic library. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - *****************************************************************************/ - -/* Standard Headers */ -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <stdlib.h> -#include <math.h> - -/* Local headers */ -#include "XvidVbr.h" - -/****************************************************************************** - * Build time constants - *****************************************************************************/ - -/* - * Portability note - * Perhaps the msvc headers define Pi with another constant name - */ -#define DEG2RAD (M_PI / 180.0) - -/* Defaults settings will be computed with the help of these constants */ -#define DEFAULT_DESIRED_SIZE 700 -#define DEFAULT_AUDIO_BITRATE 128 -#define DEFAULT_MOVIE_LENGTH 2 -#define DEFAULT_TWOPASS_BOOST 1000 -#define DEFAULT_FPS 25.0f -#define DEFAULT_CREDITS_SIZE 0 - -#define DEFAULT_XVID_DBG_FILE "xvid.dbg" -#define DEFAULT_XVID_STATS_FILE "xvid.stats" - - -/****************************************************************************** - * Local prototypes - *****************************************************************************/ - -/* Sub vbrInit cases functions */ -static vbr_init_function vbr_init_dummy; -static vbr_init_function vbr_init_2pass1; -static vbr_init_function vbr_init_2pass2; -static vbr_init_function vbr_init_fixedquant; - -/* Sub vbrGetQuant cases functions */ -static vbr_get_quant_function vbr_getquant_1pass; -static vbr_get_quant_function vbr_getquant_2pass1; -static vbr_get_quant_function vbr_getquant_2pass2; -static vbr_get_quant_function vbr_getquant_fixedquant; - -/* Sub vbrGetIntra cases functions */ -static vbr_get_intra_function vbr_getintra_1pass; -static vbr_get_intra_function vbr_getintra_2pass1; -static vbr_get_intra_function vbr_getintra_2pass2; -static vbr_get_intra_function vbr_getintra_fixedquant; - -/* Sub vbrUpdate prototypes */ -static vbr_update_function vbr_update_dummy; -static vbr_update_function vbr_update_2pass1; -static vbr_update_function vbr_update_2pass2; - -/* Sub vbrFinish cases functions */ -static vbr_finish_function vbr_finish_dummy; -static vbr_finish_function vbr_finish_2pass1; -static vbr_finish_function vbr_finish_2pass2; - -/* Is the encoder in the credits */ -#define FRAME_TYPE_NORMAL_MOVIE 0x00 -#define FRAME_TYPE_STARTING_CREDITS 0x01 -#define FRAME_TYPE_ENDING_CREDITS 0x02 - -/****************************************************************************** - * Inline utility functions - *****************************************************************************/ - -static __inline int util_frametype(vbr_control_t *state) -{ - - if(state->credits_start) { - - if(state->cur_frame >= state->credits_start_begin && - state->cur_frame < state->credits_start_end) - return(FRAME_TYPE_STARTING_CREDITS); - - } - - if(state->credits_end) { - - if(state->cur_frame >= state->credits_end_begin && - state->cur_frame < state->credits_end_end) - return(FRAME_TYPE_ENDING_CREDITS); - - } - - return(FRAME_TYPE_NORMAL_MOVIE); - - -} - -static __inline int util_creditsframes(vbr_control_t *state) -{ - - int frames = 0; - - if(state->credits_start) - frames += state->credits_start_end - state->credits_start_begin; - if(state->credits_end) - frames += state->credits_end_end - state->credits_end_begin; - - return(frames); - -} - -/****************************************************************************** - * Functions - *****************************************************************************/ - -/***************************************************************************** - * Function description : - * - * This function initialiazes the vbr_control_t with safe defaults for all - * modes. - * - * Return Values : - * = 0 - ****************************************************************************/ - -int vbrSetDefaults(vbr_control_t *state) -{ - - /* Set all the structure to zero */ - memset(state, 0, sizeof(state)); - - /* Default mode is CBR */ - state->mode = VBR_MODE_1PASS; - - /* Default statistic filename */ - state->filename = DEFAULT_XVID_STATS_FILE; - - /* - * Default is a 2hour movie on 700Mo CD-ROM + 128kbit sound track - * This represents a target bitrate of 687kbit/s - */ - state->desired_size = DEFAULT_DESIRED_SIZE*1024*1024 - - DEFAULT_MOVIE_LENGTH*3600*DEFAULT_AUDIO_BITRATE*1000/8; - state->desired_bitrate = state->desired_size*8/(DEFAULT_MOVIE_LENGTH*3600); - - /* Credits */ - state->credits_mode = VBR_CREDITS_MODE_RATE; - state->credits_start = 0; - state->credits_start_begin = 0; - state->credits_start_end = 0; - state->credits_end = 0; - state->credits_end_begin = 0; - state->credits_end_end = 0; - state->credits_quant_ratio = 20; - state->credits_fixed_quant = 20; - state->credits_quant_i = 20; - state->credits_quant_p = 20; - state->credits_start_size = DEFAULT_CREDITS_SIZE*1024*1024; - state->credits_end_size = DEFAULT_CREDITS_SIZE*1024*1024; - - /* Keyframe boost */ - state->keyframe_boost = 0; - state->kftreshold = 10; - state->kfreduction = 30; - state->min_key_interval = 1; - state->max_key_interval = (int)DEFAULT_FPS*10; - - /* Normal curve treatment */ - state->curve_compression_high = 25; - state->curve_compression_low = 10; - - /* Alt curve */ - state->use_alt_curve = 1; - state->alt_curve_type = VBR_ALT_CURVE_LINEAR; - state->alt_curve_low_dist = 90; - state->alt_curve_high_dist = 500; - state->alt_curve_min_rel_qual = 50; - state->alt_curve_use_auto = 1; - state->alt_curve_auto_str = 30; - state->alt_curve_use_auto_bonus_bias = 1; - state->alt_curve_bonus_bias = 50; - state->bitrate_payback_method = VBR_PAYBACK_BIAS; - state->bitrate_payback_delay = 250; - state->twopass_max_bitrate = DEFAULT_TWOPASS_BOOST*state->desired_bitrate; - state->twopass_max_overflow_improvement = 60; - state->twopass_max_overflow_degradation = 60; - state->max_iquant = 31; - state->min_iquant = 2; - state->max_pquant = 31; - state->min_pquant = 2; - state->fixed_quant = 3; - - state->max_framesize = (1.0/(float)DEFAULT_FPS) * state->twopass_max_bitrate / 8; - - state->fps = (float)DEFAULT_FPS; - - return(0); - -} - -/***************************************************************************** - * Function description : - * - * This function initialiaze the vbr_control_t state passed in parameter. - * - * The initialization depends on state->mode, there are 4 modes allowed. - * Each mode description is done in the README file shipped with the lib. - * - * Return values : - * - * = 0 on success - * = -1 on error - *****************************************************************************/ - -int vbrInit(vbr_control_t *state) -{ - - if(state == NULL) return(-1); - - /* Function pointers safe initialization */ - state->init = NULL; - state->getquant = NULL; - state->getintra = NULL; - state->update = NULL; - state->finish = NULL; - - if(state->debug) { - - state->debug_file = fopen(DEFAULT_XVID_DBG_FILE, "w+"); - - if(state->debug_file == NULL) - return(-1); - - fprintf(state->debug_file, "# XviD Debug output\n"); - fprintf(state->debug_file, "# quant | intra | header bytes" - "| total bytes | kblocks | mblocks | ublocks" - "| vbr overflow | vbr kf overflow" - "| vbr kf partial overflow\n\n"); - } - - /* Function pointers sub case initialization */ - switch(state->mode) { - case VBR_MODE_1PASS: - state->init = vbr_init_dummy; - state->getquant = vbr_getquant_1pass; - state->getintra = vbr_getintra_1pass; - state->update = vbr_update_dummy; - state->finish = vbr_finish_dummy; - break; - case VBR_MODE_2PASS_1: - state->init = vbr_init_2pass1; - state->getquant = vbr_getquant_2pass1; - state->getintra = vbr_getintra_2pass1; - state->update = vbr_update_2pass1; - state->finish = vbr_finish_2pass1; - break; - case VBR_MODE_FIXED_QUANT: - state->init = vbr_init_fixedquant; - state->getquant = vbr_getquant_fixedquant; - state->getintra = vbr_getintra_fixedquant; - state->update = vbr_update_dummy; - state->finish = vbr_finish_dummy; - break; - case VBR_MODE_2PASS_2: - state->init = vbr_init_2pass2; - state->getintra = vbr_getintra_2pass2; - state->getquant = vbr_getquant_2pass2; - state->update = vbr_update_2pass2; - state->finish = vbr_finish_2pass2; - break; - default: - return(-1); - } - - return(state->init(state)); - -} - -/****************************************************************************** - * Function description : - * - * This function returns an adapted quantizer according to the current vbr - * controler state - * - * Return values : - * the quantizer value (0 <= value <= 31) - * (0 is a special case, means : let XviD decide) - * - *****************************************************************************/ - -int vbrGetQuant(vbr_control_t *state) -{ - - /* Returns Zero, so XviD decides alone */ - if(state == NULL || state->getquant == NULL) return(0); - - return(state->getquant(state)); - -} - -/****************************************************************************** - * Function description : - * - * This function returns the type of the frame to be encoded next (I or P/B) - * - * Return values : - * = -1 let the XviD encoder decide wether or not the next frame is I - * = 0 no I frame - * = 1 force keyframe - * - *****************************************************************************/ - -int vbrGetIntra(vbr_control_t *state) -{ - - /* Returns -1, means let XviD decide */ - if(state == NULL || state->getintra == NULL) return(-1); - - return(state->getintra(state)); - -} - -/****************************************************************************** - * Function description : - * - * This function updates the vbr control state according to collected statistics - * from XviD core - * - * Return values : - * - * = 0 on success - * = -1 on error - *****************************************************************************/ - -int vbrUpdate(vbr_control_t *state, - int quant, - int intra, - int header_bytes, - int total_bytes, - int kblocks, - int mblocks, - int ublocks) -{ - - if(state == NULL || state->update == NULL) return(-1); - - if(state->debug && state->debug_file != NULL) { - int idx; - - fprintf(state->debug_file, "%d %d %d %d %d %d %d %d %d %d\n", - quant, intra, header_bytes, total_bytes, kblocks, - mblocks, ublocks, state->overflow, state->KFoverflow, - state->KFoverflow_partial); - - idx = quant; - - if(quant < 1) - idx = 1; - if(quant > 31) - idx = 31; - - idx--; - - state->debug_quant_count[idx]++; - - } - - return(state->update(state, quant, intra, header_bytes, total_bytes, - kblocks, mblocks, ublocks)); - -} - -/****************************************************************************** - * Function description : - * - * This function stops the vbr controller - * - * Return values : - * - * = 0 on success - * = -1 on error - *****************************************************************************/ - -int vbrFinish(vbr_control_t *state) -{ - - if(state == NULL || state->finish == NULL) return(-1); - - if(state->debug && state->debug_file != NULL) { - - int i; - - fprintf(state->debug_file, "\n\n"); - - for(i=0; i<79; i++) - fprintf(state->debug_file, "#"); - - fprintf(state->debug_file, "\n# Quantizer distribution :\n\n"); - - for(i=0;i<32; i++) { - - fprintf(state->debug_file, "# quant %d : %d\n", - i+1, - state->debug_quant_count[i]); - - } - - fclose(state->debug_file); - - } - - return(state->finish(state)); - -} - -/****************************************************************************** - * Dummy functions - Used when a mode does not need such a function - *****************************************************************************/ - -static int vbr_init_dummy(void *sstate) -{ - - vbr_control_t *state = sstate; - - state->cur_frame = 0; - - return(0); - -} - -static int vbr_update_dummy(void *state, - int quant, - int intra, - int header_bytes, - int total_bytes, - int kblocks, - int mblocks, - int ublocks) -{ - - ((vbr_control_t*)state)->cur_frame++; - - return(0); - -} - -static int vbr_finish_dummy(void *state) -{ - - return(0); - -} - -/****************************************************************************** - * 1 pass mode - XviD will do its job alone. - *****************************************************************************/ - -static int vbr_getquant_1pass(void *state) -{ - - return(0); - -} - -static int vbr_getintra_1pass(void *state) -{ - - return(-1); - -} - -/****************************************************************************** - * 2 pass mode - first pass functions - *****************************************************************************/ - -static int vbr_init_2pass1(void *sstate) -{ - - FILE *f; - vbr_control_t *state = sstate; - - /* Check the filename */ - if(state->filename == NULL || state->filename[0] == '\0') - return(-1); - - /* Initialize safe defaults for 2pass 1 */ - state->pass1_file = NULL; - state->nb_frames = 0; - state->nb_keyframes = 0; - state->cur_frame = 0; - - /* Open the 1st pass file */ - if((f = fopen(state->filename, "w+")) == NULL) - return(-1); - - /* - * The File Header - * - * The extra white spaces will be used during the vbrFinish to write - * the resulting number of frames and keyframes (10 spaces == maximum - * string length of an int on 32bit machines, i don't think anyone is - * encoding more than 4 billion frames :-) - */ - fprintf(f, "# ASCII XviD vbr stat file version %d\n#\n", VBR_VERSION); - fprintf(f, "# frames : \n"); - fprintf(f, "# keyframes : \n"); - fprintf(f, "#\n# quant | intra | header bytes | total bytes | kblocks |" - " mblocks | ublocks\n\n"); - - /* Save file pointer */ - state->pass1_file = f; - - return(0); - -} - -static int vbr_getquant_2pass1(void *state) -{ - - return(2); - -} - -static int vbr_getintra_2pass1(void *state) -{ - - return(-1); - -} - -static int vbr_update_2pass1(void *sstate, - int quant, - int intra, - int header_bytes, - int total_bytes, - int kblocks, - int mblocks, - int ublocks) - - -{ - - vbr_control_t *state = sstate; - - if(state->pass1_file == NULL) - return(-1); - - /* Writes the resulting statistics */ - fprintf(state->pass1_file, "%d %d %d %d %d %d %d\n", - quant, - intra, - header_bytes, - total_bytes, - kblocks, - mblocks, - ublocks); - - /* Update vbr control state */ - if(intra) state->nb_keyframes++; - state->nb_frames++; - state->cur_frame++; - - return(0); - -} - -static int vbr_finish_2pass1(void *sstate) -{ - - int c, i; - vbr_control_t *state = sstate; - - if(state->pass1_file == NULL) - return(-1); - - /* Goto to the file beginning */ - fseek(state->pass1_file, 0, SEEK_SET); - - /* Skip the version line and the empty line */ - c = i = 0; - do { - c = fgetc(state->pass1_file); - - if(c == EOF) return(-1); - if(c == '\n') i++; - - }while(i < 2); - - /* Prepare to write to the stream */ - fseek( state->pass1_file, 0L, SEEK_CUR ); - - /* Overwrite the frame field - safe as we have written extra spaces */ - fprintf(state->pass1_file, "# frames : %.10d\n", state->nb_frames); - - /* Overwrite the keyframe field */ - fprintf(state->pass1_file, "# keyframes : %.10d\n", - state->nb_keyframes); - - /* Close the file */ - if(fclose(state->pass1_file) != 0) - return(-1); - - return(0); - -} - -/****************************************************************************** - * 2 pass mode - 2nd pass functions (Need to be finished) - *****************************************************************************/ - -static int vbr_init_2pass2(void *sstate) -{ - - FILE *f; - int c, n, pos_firstframe, credits_frames; - long long credits1_bytes; - long long credits2_bytes; - long long desired; - long long total_bytes; - long long itotal_bytes; - long long start_curved; - long long end_curved; - double total1; - double total2; - - vbr_control_t *state = sstate; - - /* Check the filename */ - if(state->filename == NULL || state->filename[0] == '\0') - return(-1); - - /* Initialize safe defaults for 2pass 2 */ - state->pass1_file = NULL; - state->nb_frames = 0; - state->nb_keyframes = 0; - - /* Open the 1st pass file */ - if((f = fopen(state->filename, "r")) == NULL) - return(-1); - - state->pass1_file = f; - - /* Get the file version and check against current version */ - fscanf(state->pass1_file, "# ASCII XviD vbr stat file version %d\n", &n); - - if(n != VBR_VERSION) { - fclose(state->pass1_file); - state->pass1_file = NULL; - return(-1); - } - - /* Skip the blank commented line */ - c = n = 0; - do { - - c = fgetc(state->pass1_file); - - if(c == EOF) { - fclose(state->pass1_file); - state->pass1_file = NULL; - return(-1); - } - - if(c == '\n') n++; - - }while(n < 1); - - - /* Get the number of frames */ - fscanf(state->pass1_file, "# frames : %d\n", &state->nb_frames); - - /* Compute the desired size */ - state->desired_size = (long long) - (((long long)state->nb_frames * (long long)state->desired_bitrate) / - (state->fps * 8.0)); - - /* Get the number of keyframes */ - fscanf(state->pass1_file, "# keyframes : %d\n", &state->nb_keyframes); - - /* Allocate memory space for the keyframe_location array */ - if((state->keyframe_locations - = (int*)malloc((state->nb_keyframes+1)*sizeof(int))) == NULL) { - fclose(state->pass1_file); - state->pass1_file = NULL; - return(-1); - } - - /* Skip the blank commented line and the colum description */ - c = n = 0; - do { - - c = fgetc(state->pass1_file); - - if(c == EOF) { - fclose(state->pass1_file); - state->pass1_file = NULL; - return(-1); - } - - if(c == '\n') n++; - - }while(n < 2); - - /* Save position for future use */ - pos_firstframe = ftell(state->pass1_file); - - /* Read and initialize some variables */ - credits1_bytes = credits2_bytes = 0; - total_bytes = itotal_bytes = 0; - start_curved = end_curved = 0; - credits_frames = 0; - - for(state->cur_frame = c = 0; state->cur_frame<state->nb_frames; state->cur_frame++) { - - int quant, keyframe, frame_hbytes, frame_bytes; - int kblocks, mblocks, ublocks; - - fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n", - &quant, &keyframe, &frame_hbytes, &frame_bytes, - &kblocks, &mblocks, &ublocks); - - /* Is the frame in the beginning credits */ - if(util_frametype(state) == FRAME_TYPE_STARTING_CREDITS) { - credits1_bytes += frame_bytes; - credits_frames++; - continue; - } - - /* Is the frame in the eding credits */ - if(util_frametype(state) == FRAME_TYPE_ENDING_CREDITS) { - credits2_bytes += frame_bytes; - credits_frames++; - continue; - } - - /* We only care about Keyframes when not in credits */ - if(keyframe) { - itotal_bytes += frame_bytes + frame_bytes * - state->keyframe_boost / 100; - total_bytes += frame_bytes * - state->keyframe_boost / 100; - state->keyframe_locations[c++] = state->cur_frame; - } - - total_bytes += frame_bytes; - - } - - /* - * Last frame is treated like an I Frame so we can dispatch overflow - * all other the last film segment - */ - state->keyframe_locations[c] = state->cur_frame; - - desired = state->desired_size; - - switch(state->credits_mode) { - case VBR_CREDITS_MODE_QUANT : - - state->movie_curve = (double) - (total_bytes - credits1_bytes - credits2_bytes) / - (desired - credits1_bytes - credits2_bytes); - - start_curved = credits1_bytes; - end_curved = credits2_bytes; - - break; - case VBR_CREDITS_MODE_SIZE: - - /* start curve = (start / start desired size) */ - state->credits_start_curve = (double) - (credits1_bytes / state->credits_start_size); - - /* end curve = (end / end desired size) */ - state->credits_end_curve = (double) - (credits2_bytes / state->credits_end_size); - - start_curved = (long long) - (credits1_bytes / state->credits_start_curve); - - end_curved = (long long) - (credits2_bytes / state->credits_end_curve); - - /* movie curve=(total-credits)/(desired_size-curved credits) */ - state->movie_curve = (double) - (total_bytes - credits1_bytes - credits2_bytes) / - (desired - start_curved - end_curved); - - break; - case VBR_CREDITS_MODE_RATE: - default: - - /* credits curve = (total/desired_size)*(100/credits_rate) */ - state->credits_start_curve = state->credits_end_curve = - ((double)total_bytes / desired) * - ((double)100 / state->credits_quant_ratio); - - start_curved = - (long long)(credits1_bytes/state->credits_start_curve); - - end_curved = - (long long)(credits2_bytes/state->credits_end_curve); - - state->movie_curve = (double) - (total_bytes - credits1_bytes - credits2_bytes) / - (desired - start_curved - end_curved); - - break; - } - - /* - * average frame size = (desired - curved credits - curved keyframes) / - * (frames - credits frames - keyframes) - */ - state->average_frame = (double) - (desired - start_curved - end_curved - - (itotal_bytes / state->movie_curve)) / - (state->nb_frames - util_creditsframes(state) - - state->nb_keyframes); - - /* Initialize alt curve parameters */ - if (state->use_alt_curve) { - - state->alt_curve_low = - state->average_frame - state->average_frame * - (double)(state->alt_curve_low_dist / 100.0); - - state->alt_curve_low_diff = - state->average_frame - state->alt_curve_low; - - state->alt_curve_high = - state->average_frame + state->average_frame * - (double)(state->alt_curve_high_dist / 100.0); - - state->alt_curve_high_diff = - state->alt_curve_high - state->average_frame; - - if (state->alt_curve_use_auto) { - - if (state->movie_curve > 1.0) { - - state->alt_curve_min_rel_qual = - (int)(100.0 - (100.0 - 100.0 / state->movie_curve) * - (double)state->alt_curve_auto_str / 100.0); - - if (state->alt_curve_min_rel_qual < 20) - state->alt_curve_min_rel_qual = 20; - } - else { - state->alt_curve_min_rel_qual = 100; - } - - } - - state->alt_curve_mid_qual = - (1.0 + (double)state->alt_curve_min_rel_qual / 100.0) / 2.0; - - state->alt_curve_qual_dev = 1.0 - state->alt_curve_mid_qual; - - if (state->alt_curve_low_dist > 100) { - - switch(state->alt_curve_type) { - case VBR_ALT_CURVE_AGGRESIVE: - /* Sine Curve (high aggressiveness) */ - state->alt_curve_qual_dev *= - 2.0 / - (1.0 + sin(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff))); - - state->alt_curve_mid_qual = - 1.0 - state->alt_curve_qual_dev * - sin(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff)); - break; - - default: - case VBR_ALT_CURVE_LINEAR: - /* Linear (medium aggressiveness) */ - state->alt_curve_qual_dev *= - 2.0 / - (1.0 + state->average_frame / state->alt_curve_low_diff); - - state->alt_curve_mid_qual = - 1.0 - state->alt_curve_qual_dev * - state->average_frame / state->alt_curve_low_diff; - - break; - - case VBR_ALT_CURVE_SOFT: - /* Cosine Curve (low aggressiveness) */ - state->alt_curve_qual_dev *= - 2.0 / - (1.0 + (1.0 - cos(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff)))); - - state->alt_curve_mid_qual = - 1.0 - state->alt_curve_qual_dev * - (1.0 - cos(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff))); - - break; - } - } - } - - /* Go to the first non credits frame stats line into file */ - fseek(state->pass1_file, pos_firstframe, SEEK_SET); - - /* Perform prepass to compensate for over/undersizing */ - total1 = total2 = 0.0; - for(state->cur_frame=0; state->cur_frame<state->nb_frames; state->cur_frame++) { - - int quant, keyframe, frame_hbytes, frame_bytes; - int kblocks, mblocks, ublocks; - - fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n", - &quant, &keyframe, &frame_hbytes, &frame_bytes, - &kblocks, &mblocks, &ublocks); - - if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) - continue; - - if(!keyframe) { - - double dbytes = frame_bytes / state->movie_curve; - total1 += dbytes; - - if (state->use_alt_curve) { - - if (dbytes > state->average_frame) { - - if (dbytes >= state->alt_curve_high) { - total2 += dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev); - } - else { - - switch(state->alt_curve_type) { - case VBR_ALT_CURVE_AGGRESIVE: - - total2 += - dbytes * - (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff))); - break; - default: - case VBR_ALT_CURVE_LINEAR: - - total2 += - dbytes * - (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (dbytes - state->average_frame) / state->alt_curve_high_diff); - break; - case VBR_ALT_CURVE_SOFT: - total2 += - dbytes * - (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff)))); - } - } - } - else { - - if (dbytes <= state->alt_curve_low) { - total2 += dbytes; - } - else { - - switch(state->alt_curve_type) { - case VBR_ALT_CURVE_AGGRESIVE: - total2 += - dbytes * - (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff))); - break; - default: - case VBR_ALT_CURVE_LINEAR: - total2 += - dbytes * - (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (dbytes - state->average_frame) / state->alt_curve_low_diff); - break; - case VBR_ALT_CURVE_SOFT: - total2 += - dbytes * - (state->alt_curve_mid_qual + state->alt_curve_qual_dev * - (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff)))); - } - } - } - } - else { - if (dbytes > state->average_frame) { - total2 += - ((double)dbytes + - (state->average_frame - dbytes) * - state->curve_compression_high / 100.0); - } - else { - total2 += - ((double)dbytes + - (state->average_frame - dbytes) * - state->curve_compression_low / 100.0); - } - } - } - } - - state->curve_comp_scale = total1 / total2; - - if (state->use_alt_curve) { - - double curve_temp, dbytes; - int newquant, percent; - int oldquant = 1; - - if (state->alt_curve_use_auto_bonus_bias) - state->alt_curve_bonus_bias = state->alt_curve_min_rel_qual; - - state->curve_bias_bonus = - (total1 - total2) * (double)state->alt_curve_bonus_bias / - (100.0 * (double)(state->nb_frames - util_creditsframes(state) - state->nb_keyframes)); - state->curve_comp_scale = - ((total1 - total2) * (1.0 - (double)state->alt_curve_bonus_bias / 100.0) + total2) / - total2; - - - for (n=1; n <= (int)(state->alt_curve_high*2) + 1; n++) { - dbytes = n; - if (dbytes > state->average_frame) - { - if (dbytes >= state->alt_curve_high) { - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev); - } - else { - switch(state->alt_curve_type) { - case VBR_ALT_CURVE_AGGRESIVE: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff))); - break; - default: - case VBR_ALT_CURVE_LINEAR: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (dbytes - state->average_frame) / state->alt_curve_high_diff); - break; - case VBR_ALT_CURVE_SOFT: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff)))); - } - } - } - else { - if (dbytes <= state->alt_curve_low) { - curve_temp = dbytes; - } - else { - switch(state->alt_curve_type) { - case VBR_ALT_CURVE_AGGRESIVE: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff))); - break; - default: - case VBR_ALT_CURVE_LINEAR: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (dbytes - state->average_frame) / state->alt_curve_low_diff); - break; - case VBR_ALT_CURVE_SOFT: - curve_temp = dbytes * (state->alt_curve_mid_qual + state->alt_curve_qual_dev * - (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff)))); - } - } - } - - if (state->movie_curve > 1.0) - dbytes *= state->movie_curve; - - newquant = (int)(dbytes * 2.0 / (curve_temp * state->curve_comp_scale + state->curve_bias_bonus)); - if (newquant > 1) - { - if (newquant != oldquant) - { - oldquant = newquant; - percent = (int)((n - state->average_frame) * 100.0 / state->average_frame); - } - - } - - } - - } - - state->overflow = 0; - state->KFoverflow = 0; - state->KFoverflow_partial = 0; - state->KF_idx = 1; - - for (n=0 ; n < 32 ; n++) { - state->quant_error[n] = 0.0; - state->quant_count[n] = 0; - } - - state->curve_comp_error = 0.0; - state->last_quant = 0; - - /* - * Above this frame size limit, normal vbr rules will not apply - * This means : - * 1 - Quant can de/increase more than -/+2 between 2 frames - * 2 - Leads to artifacts because of 1 - */ - state->max_framesize = state->twopass_max_bitrate/state->fps; - - /* Get back to the beginning of frame statistics */ - fseek(state->pass1_file, pos_firstframe, SEEK_SET); - - /* - * Small hack : We have to get next frame stats before the - * getintra/quant calls - * User clients update the data when they call vbrUpdate - * we are just bypassing this because we don't have to update - * the overflow and so on... - */ - { - - /* Fake vars */ - int next_hbytes, next_kblocks, next_mblocks, next_ublocks; - - fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n", - &state->pass1_quant, &state->pass1_intra, &next_hbytes, - &state->pass1_bytes, &next_kblocks, &next_mblocks, - &next_ublocks); - - } - - /* Initialize the frame counter */ - state->cur_frame = 0; - state->last_keyframe = 0; - - return(0); - -} - -static int vbr_getquant_2pass2(void *sstate) -{ - - int quant; - int intra; - int bytes1, bytes2; - int overflow; - int capped_to_max_framesize = 0; - int KFdistance, KF_min_size; - vbr_control_t *state = sstate; - - bytes1 = state->pass1_bytes; - overflow = state->overflow / 8; - /* To shut up gcc warning */ - bytes2 = bytes1; - - - if (state->pass1_intra) - { - overflow = 0; - } - - if (util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) { - - - switch (state->credits_mode) { - case VBR_CREDITS_MODE_QUANT : - if (state->credits_quant_i != state->credits_quant_p) { - quant = state->pass1_intra ? - state->credits_quant_i: - state->credits_quant_p; - } - else { - quant = state->credits_quant_p; - } - - state->bytes1 = bytes1; - state->bytes2 = bytes1; - state->desired_bytes2 = bytes1; - return(quant); - default: - case VBR_CREDITS_MODE_RATE : - case VBR_CREDITS_MODE_SIZE : - if(util_frametype(state) == FRAME_TYPE_STARTING_CREDITS) - bytes2 = (int)(bytes1 / state->credits_start_curve); - else - bytes2 = (int)(bytes1 / state->credits_end_curve); - break; - } - } - else { - /* Foxer: apply curve compression outside credits */ - double dbytes, curve_temp; - - bytes2 = bytes1; - - if (state->pass1_intra) - dbytes = ((int)(bytes2 + bytes2 * state->keyframe_boost / 100)) / - state->movie_curve; - else - dbytes = bytes2 / state->movie_curve; - - /* spread the compression error accross payback_delay frames */ - if (state->bitrate_payback_method == VBR_PAYBACK_BIAS) { - bytes2 = (int)(state->curve_comp_error / state->bitrate_payback_delay); - } - else { - bytes2 = (int)(state->curve_comp_error * dbytes / - state->average_frame / state->bitrate_payback_delay); - - if (labs(bytes2) > fabs(state->curve_comp_error)) - bytes2 = (int)state->curve_comp_error; - } - - state->curve_comp_error -= bytes2; - - if (state->use_alt_curve) { - - if (!state->pass1_intra) { - - if (dbytes > state->average_frame) { - if (dbytes >= state->alt_curve_high) - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev); - else { - switch(state->alt_curve_type) { - case VBR_ALT_CURVE_AGGRESIVE: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff))); - break; - default: - case VBR_ALT_CURVE_LINEAR: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (dbytes - state->average_frame) / state->alt_curve_high_diff); - break; - case VBR_ALT_CURVE_SOFT: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff)))); - } - } - } - else { - if (dbytes <= state->alt_curve_low) - curve_temp = dbytes; - else { - switch(state->alt_curve_type) { - case VBR_ALT_CURVE_AGGRESIVE: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff))); - break; - default: - case VBR_ALT_CURVE_LINEAR: - curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * - (dbytes - state->average_frame) / state->alt_curve_low_diff); - break; - case VBR_ALT_CURVE_SOFT: - curve_temp = dbytes * (state->alt_curve_mid_qual + state->alt_curve_qual_dev * - (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff)))); - } - } - } - - curve_temp = curve_temp * state->curve_comp_scale + state->curve_bias_bonus; - - bytes2 += ((int)curve_temp); - state->curve_comp_error += curve_temp - ((int)curve_temp); - - } - else { - state->curve_comp_error += dbytes - ((int)dbytes); - bytes2 += ((int)dbytes); - } - } - else if ((state->curve_compression_high + state->curve_compression_low) && - !state->pass1_intra) { - - if (dbytes > state->average_frame) { - curve_temp = state->curve_comp_scale * - ((double)dbytes + (state->average_frame - dbytes) * - state->curve_compression_high / 100.0); - } - else { - curve_temp = state->curve_comp_scale * - ((double)dbytes + (state->average_frame - dbytes) * - state->curve_compression_low / 100.0); - } - - bytes2 += ((int)curve_temp); - state->curve_comp_error += curve_temp - ((int)curve_temp); - } - else { - state->curve_comp_error += dbytes - ((int)dbytes); - bytes2 += ((int)dbytes); - } - - /* cap bytes2 to first pass size, lowers number of quant=1 frames */ - if (bytes2 > bytes1) { - state->curve_comp_error += bytes2 - bytes1; - bytes2 = bytes1; - } - else if (bytes2 < 1) { - state->curve_comp_error += --bytes2; - bytes2 = 1; - } - } - - state->desired_bytes2 = bytes2; - - /* Ugly dependance between getquant and getintra */ - intra = state->getintra(state); - - if(intra) { - - KFdistance = state->keyframe_locations[state->KF_idx] - - state->keyframe_locations[state->KF_idx - 1]; - - if (KFdistance < state->kftreshold) { - KFdistance = KFdistance - state->min_key_interval; - - if (KFdistance >= 0) { - - KF_min_size = bytes2 * (100 - state->kfreduction) / 100; - if (KF_min_size < 1) - KF_min_size = 1; - - bytes2 = KF_min_size + (bytes2 - KF_min_size) * KFdistance / - (state->kftreshold - state->min_key_interval); - - if (bytes2 < 1) - bytes2 = 1; - } - } - } - - /* - * Foxer: scale overflow in relation to average size, so smaller frames don't get - * too much/little bitrate - */ - overflow = (int)((double)overflow * bytes2 / state->average_frame); - - /* Foxer: reign in overflow with huge frames */ - if (labs(overflow) > labs(state->overflow)) { - overflow = state->overflow; - } - - /* Foxer: make sure overflow doesn't run away */ - if(overflow > bytes2 * state->twopass_max_overflow_improvement / 100) { - bytes2 += (overflow <= bytes2) ? bytes2 * state->twopass_max_overflow_improvement / 100 : - overflow * state->twopass_max_overflow_improvement / 100; - } - else if(overflow < bytes2 * state->twopass_max_overflow_degradation / -100) { - bytes2 += bytes2 * state->twopass_max_overflow_degradation / -100; - } - else { - bytes2 += overflow; - } - - if(bytes2 > state->max_framesize) { - capped_to_max_framesize = 1; - bytes2 = state->max_framesize; - } - - if(bytes2 < 1) { - bytes2 = 1; - } - - state->bytes1 = bytes1; - state->bytes2 = bytes2; - - /* very 'simple' quant<->filesize relationship */ - quant = state->pass1_quant * bytes1 / bytes2; - - if(quant < 1) - quant = 1; - else if(quant > 31) - quant = 31; - else if(!state->pass1_intra) { - - /* Foxer: aid desired quantizer precision by accumulating decision error */ - state->quant_error[quant] += ((double)(state->pass1_quant * bytes1) / bytes2) - quant; - - if (state->quant_error[quant] >= 1.0) { - state->quant_error[quant] -= 1.0; - quant++; - } - } - - /* we're done with credits */ - if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) { - return(quant); - } - - if(intra) { - - if (quant < state->min_iquant) - quant = state->min_iquant; - if (quant > state->max_iquant) - quant = state->max_iquant; - } - else { - - if(quant > state->max_pquant) - quant = state->max_pquant; - if(quant < state->min_pquant) - quant = state->min_pquant; - - /* subsequent frame quants can only be +- 2 */ - if(state->last_quant && capped_to_max_framesize == 0) { - if (quant > state->last_quant + 2) - quant = state->last_quant + 2; - if (quant < state->last_quant - 2) - quant = state->last_quant - 2; - } - } - - return(quant); - -} - -static int vbr_getintra_2pass2(void *sstate) -{ - - int intra; - vbr_control_t *state = sstate; - - - /* Get next intra state (fetched by update) */ - intra = state->pass1_intra; - - /* During credits, XviD will decide itself */ - if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) { - - - switch(state->credits_mode) { - default: - case VBR_CREDITS_MODE_RATE : - case VBR_CREDITS_MODE_SIZE : - intra = -1; - break; - case VBR_CREDITS_MODE_QUANT : - /* Except in this case */ - if (state->credits_quant_i == state->credits_quant_p) - intra = -1; - break; - } - - } - - /* Force I Frame when max_key_interval is reached */ - if((state->cur_frame - state->last_keyframe) > state->max_key_interval) - intra = 1; - - /* - * Force P or B Frames for frames whose distance is less than the - * requested minimum - */ - if((state->cur_frame - state->last_keyframe) < state->min_key_interval) - intra = 0; - - - /* Return the given intra mode except for first frame */ - return((state->cur_frame==0)?1:intra); - -} - -static int vbr_update_2pass2(void *sstate, - int quant, - int intra, - int header_bytes, - int total_bytes, - int kblocks, - int mblocks, - int ublocks) - - -{ - - - int next_hbytes, next_kblocks, next_mblocks, next_ublocks; - int tempdiv; - - vbr_control_t *state = sstate; - - /* - * We do not depend on getintra/quant because we have the real results - * from the xvid core - */ - - if (util_frametype(state) == FRAME_TYPE_NORMAL_MOVIE) { - - state->quant_count[quant]++; - - if (state->pass1_intra) { - - state->overflow += state->KFoverflow; - state->KFoverflow = state->desired_bytes2 - total_bytes; - - tempdiv = (state->keyframe_locations[state->KF_idx] - - state->keyframe_locations[state->KF_idx - 1]); - - /* redistribute correctly (by koepi) */ - if (tempdiv > 1) { - /* non-consecutive keyframes */ - state->KFoverflow_partial = state->KFoverflow / - (tempdiv - 1); - } - else { - state->overflow += state->KFoverflow; - state->KFoverflow = 0; - state->KFoverflow_partial = 0; - } - state->KF_idx++; - - } - else { - state->overflow += state->desired_bytes2 - total_bytes + - state->KFoverflow_partial; - state->KFoverflow -= state->KFoverflow_partial; - } - } - else { - - state->overflow += state->desired_bytes2 - total_bytes; - state->overflow += state->KFoverflow; - state->KFoverflow = 0; - state->KFoverflow_partial = 0; - } - - /* Save old quant */ - state->last_quant = quant; - - /* Update next frame data */ - fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n", - &state->pass1_quant, &state->pass1_intra, &next_hbytes, - &state->pass1_bytes, &next_kblocks, &next_mblocks, - &next_ublocks); - - /* Save the last Keyframe pos */ - if(intra) - state->last_keyframe = state->cur_frame; - - /* Ok next frame */ - state->cur_frame++; - - return(0); - -} - -static int vbr_finish_2pass2(void *sstate) -{ - - vbr_control_t *state = sstate; - - if(state->pass1_file == NULL) - return(-1); - - /* Close the file */ - if(fclose(state->pass1_file) != 0) - return(-1); - - /* Free the memory */ - if(state->keyframe_locations) - free(state->keyframe_locations); - - return(0); - -} - - -/****************************************************************************** - * Fixed quant mode - Most of the functions will be dummy functions - *****************************************************************************/ - -static int vbr_init_fixedquant(void *sstate) -{ - - vbr_control_t *state = sstate; - - if(state->fixed_quant < 1) - state->fixed_quant = 1; - - if(state->fixed_quant > 31) - state->fixed_quant = 31; - - state->cur_frame = 0; - - return(0); - -} - -static int vbr_getquant_fixedquant(void *sstate) -{ - - vbr_control_t *state = sstate; - - /* Credits' frame ? */ - if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) { - - int quant; - - switch(state->credits_mode) { - case VBR_CREDITS_MODE_RATE: - quant = state->fixed_quant * state->credits_quant_ratio; - break; - case VBR_CREDITS_MODE_QUANT: - quant = state->credits_fixed_quant; - break; - default: - quant = state->fixed_quant; - - } - - return(quant); - - } - - /* No credit frame - return fixed quant */ - return(state->fixed_quant); - -} - -static int vbr_getintra_fixedquant(void *state) -{ - - return(-1); - -} diff --git a/core/XvidVbr.h b/core/XvidVbr.h deleted file mode 100644 index ea9d3b703..000000000 --- a/core/XvidVbr.h +++ /dev/null @@ -1,231 +0,0 @@ -/****************************************************************************** - * - * XviD VBR Library - * - * Copyright (C) 2002 Edouard Gomez <[email protected]> - * - * The curve treatment algorithm is based on work done by Foxer <email?> and - * Dirk Knop <[email protected]> for the XviD vfw dynamic library. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - *****************************************************************************/ - -#ifndef __XVID_VBR_H__ -#define __XVID_VBR_H__ - -#define VBR_VERSION 0 - -/****************************************************************************** - * Function types used in the vbr controler - *****************************************************************************/ - -typedef int (vbr_init_function)(void *state); -typedef vbr_init_function *vbr_init_function_ptr; - -typedef int (vbr_get_quant_function)(void *state); -typedef vbr_get_quant_function *vbr_get_quant_function_ptr; - -typedef int (vbr_get_intra_function)(void *state); -typedef vbr_get_intra_function *vbr_get_intra_function_ptr; - -typedef int (vbr_update_function)(void *state, - int quant, - int intra, - int header_bytes, - int total_bytes, - int kblocks, - int mblocks, - int ublocks); -typedef vbr_update_function *vbr_update_function_ptr; - -typedef int (vbr_finish_function)(void *state); -typedef vbr_finish_function *vbr_finish_function_ptr; - -/****************************************************************************** - * The VBR CONTROLER structure - the spin of the library - *****************************************************************************/ - -typedef struct _vbr_control_t -{ - - /* All modes - specifies what VBR algorithm has to be used */ - int mode; - - /* All modes - specifies what fps the movie uses */ - float fps; - - /* All modes */ - int debug; - - /* - * For VBR_MODE_2PASS_1/2 - specifies from/to what file the vbr - * controller has to write/read stats - */ - char *filename; - - /* For VBR_MODE_2PASS_2 - Target size */ - int desired_bitrate; - - /* For VBR_MODE_2PASS_2 - Credits parameters */ - int credits_mode; - int credits_start; - int credits_start_begin; - int credits_start_end; - int credits_end; - int credits_end_begin; - int credits_end_end; - int credits_quant_ratio; - int credits_fixed_quant; - int credits_quant_i; - int credits_quant_p; - int credits_start_size; - int credits_end_size; - - /* For VBR_MODE_2PASS_2 - keyframe parameters */ - int keyframe_boost; - int kftreshold; - int kfreduction; - int min_key_interval; - int max_key_interval; - - /* For VBR_MODE_2PASS_2 - Normal curve */ - int curve_compression_high; - int curve_compression_low; - - /* For VBR_MODE_2PASS_2 - Alternate curve parameters */ - int use_alt_curve; - int alt_curve_type; - int alt_curve_low_dist; - int alt_curve_high_dist; - int alt_curve_min_rel_qual; - int alt_curve_use_auto; - int alt_curve_auto_str; - int alt_curve_use_auto_bonus_bias; - int alt_curve_bonus_bias; - int bitrate_payback_method; - int bitrate_payback_delay; - int max_iquant; - int min_iquant; - int max_pquant; - int min_pquant; - int twopass_max_bitrate; - int twopass_max_overflow_improvement; - int twopass_max_overflow_degradation; - - /* - * For VBR_MODE_FIXED_QUANT - the quantizer that has to be used for all - * frames - */ - int fixed_quant; - - /* ----------- Internal data - Do not modify ----------- */ - void *debug_file; - void *pass1_file; - - long long desired_size; - - int cur_frame; - int nb_frames; - int nb_keyframes; - - int *keyframe_locations; - int last_keyframe; - - double credits_start_curve; - double credits_end_curve; - double movie_curve; - double average_frame; - double alt_curve_low; - double alt_curve_low_diff; - double alt_curve_high; - double alt_curve_high_diff; - double alt_curve_mid_qual; - double alt_curve_qual_dev; - double curve_bias_bonus; - double curve_comp_scale; - double curve_comp_error; - - int pass1_quant; - int pass1_intra; - int pass1_bytes; - - int bytes1; - int bytes2; - int desired_bytes2; - int max_framesize; - int last_quant; - int quant_count[32]; - double quant_error[32]; - - int overflow; - int KFoverflow; - int KFoverflow_partial; - int KF_idx; - - int debug_quant_count[32]; - - /* ----------- Internal data - do not modify ----------- */ - vbr_init_function_ptr init; - vbr_get_quant_function_ptr getquant; - vbr_get_intra_function_ptr getintra; - vbr_update_function_ptr update; - vbr_finish_function_ptr finish; - -}vbr_control_t; - -/****************************************************************************** - * Constants - *****************************************************************************/ - -/* Constants for the mode member */ -#define VBR_MODE_1PASS 0x01 -#define VBR_MODE_2PASS_1 0x02 -#define VBR_MODE_2PASS_2 0x04 -#define VBR_MODE_FIXED_QUANT 0x08 - -/* Constants for the credits mode */ -#define VBR_CREDITS_MODE_RATE 0x01 -#define VBR_CREDITS_MODE_QUANT 0x02 -#define VBR_CREDITS_MODE_SIZE 0x04 - -/* Alternate curve treatment types */ -#define VBR_ALT_CURVE_SOFT 0x01 -#define VBR_ALT_CURVE_LINEAR 0x02 -#define VBR_ALT_CURVE_AGGRESIVE 0x04 - -/* Payback modes */ -#define VBR_PAYBACK_BIAS 0x01 -#define VBR_PAYBACK_PROPORTIONAL 0x02 - -/****************************************************************************** - * VBR API - *****************************************************************************/ - -extern int vbrSetDefaults(vbr_control_t *state); -extern int vbrInit(vbr_control_t *state); -extern int vbrGetQuant(vbr_control_t *state); -extern int vbrGetIntra(vbr_control_t *state); -extern int vbrUpdate(vbr_control_t *state, - int quant, - int intra, - int header_bytes, - int total_bytes, - int kblocks, - int mblocks, - int ublocks); -extern int vbrFinish(vbr_control_t *state); - -#endif diff --git a/gtk2/callbacks.c b/gtk2/callbacks.c new file mode 100644 index 000000000..04a140678 --- /dev/null +++ b/gtk2/callbacks.c @@ -0,0 +1,623 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtk/gtk.h> + +#include "../core/HandBrake.h" +#include "status.h" + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + + +static int i_settings_preview_picture; +static int i_settings_width = 0; +static int i_settings_crop_top = 0; +static int i_settings_crop_bottom = 0; +static int i_settings_crop_left = 0; +static int i_settings_crop_right = 0; +static int b_settings_deinterlace = 0; + +gboolean on_win_main_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + HBClose( &hb_handle ); + + hb_handle = NULL; + + gtk_main_quit(); + return FALSE; +} + + +void on_button_browse_device (GtkButton *button, + gpointer user_data) +{ + GtkWidget *win_open; + + /* Create the open window */ + win_open = create_win_open(); + gtk_object_set_data( GTK_OBJECT(win_open), "entry", "entry_device" ); + gtk_widget_show( win_open ); + gdk_window_raise( win_open->window ); +} + +/*** + * Open file dialog box handle (you should have set entry to the right entry name of hb_win_main + */ +gboolean on_win_open_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + GtkWidget *win_open = gtk_widget_get_toplevel( GTK_WIDGET (widget) ); + + gtk_widget_destroy( win_open ); + return FALSE; +} + +void on_ok_button1_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *win_open = gtk_widget_get_toplevel( GTK_WIDGET (button) ); + + char *psz_entry = gtk_object_get_data( GTK_OBJECT( win_open ), "entry" ); + const char *psz_file = gtk_file_selection_get_filename( GTK_FILE_SELECTION( win_open ) ); + + GtkWidget *entry = lookup_widget( hb_win_main, psz_entry ); + + gtk_entry_set_text( GTK_ENTRY( entry ), psz_file ); + if( !strcmp( psz_entry, "entry_device" ) && *psz_file ) + { + /* Feed libhb with a device */ + HBScanDVD( hb_handle, psz_file, 0 ); + } + gtk_widget_destroy( win_open ); +} + + +void on_cancel_button1_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *win_open = gtk_widget_get_toplevel( GTK_WIDGET (button) ); + gtk_widget_destroy( win_open ); +} + +void on_entry_device_activate( GtkEntry *entry, + gpointer user_data) +{ + const char *psz_file = gtk_entry_get_text( GTK_ENTRY( entry ) ); + + /* Feed libhb with a device */ + if( *psz_file ) + { + HBScanDVD( hb_handle, psz_file, 0 ); + } +} + +static void menu_language_new( GtkOptionMenu *optionmenu, char *name, HBTitle *title, int i_default ) +{ + int i; + + /* build audio menu */ + GtkWidget *menu = gtk_menu_new(); + GtkWidget *item; + + item = gtk_menu_item_new_with_mnemonic( "None" ); + gtk_widget_show( item ); + gtk_menu_shell_append( GTK_MENU_SHELL(menu), item ); + + for( i = 0; i < HBListCount( title->audioList ); i++ ) + { + HBAudio *audio = (HBAudio*) HBListItemAt( title->audioList, i ); + + item = gtk_menu_item_new_with_mnemonic( audio->language ); + gtk_widget_show( item ); + gtk_menu_shell_append( GTK_MENU_SHELL(menu), item ); + } + + gtk_option_menu_set_menu( GTK_OPTION_MENU(optionmenu), menu ); + GLADE_HOOKUP_OBJECT( hb_win_main, menu, name ); + + gtk_option_menu_set_history( GTK_OPTION_MENU(optionmenu), i_default ); +} + +void on_optionmenu_title_changed( GtkOptionMenu *optionmenu, + gpointer user_data) +{ + GtkWidget *optionmenu_language = lookup_widget( hb_win_main, "optionmenu_language" ); + GtkWidget *optionmenu_language2 = lookup_widget( hb_win_main, "optionmenu_language2" ); + + HBTitle *title; + + int i = gtk_option_menu_get_history( optionmenu ); + + title = (HBTitle*) HBListItemAt( hb_status->titleList, i ); + + /* FIXME is it ok ?*/ + gtk_option_menu_remove_menu( GTK_OPTION_MENU(optionmenu_language) ); + gtk_option_menu_remove_menu( GTK_OPTION_MENU(optionmenu_language2) ); + + if( title ) + { + /* build audio menu */ + menu_language_new( GTK_OPTION_MENU(optionmenu_language), "menu_language", title, 1 ); + menu_language_new( GTK_OPTION_MENU(optionmenu_language2), "menu_language2", title, 0 ); + } +} + + + + + + + +void on_button_browse_file_clicked( GtkButton *button, + gpointer user_data) +{ + GtkWidget *win_open; + + /* Create the open window */ + win_open = create_win_open(); + gtk_object_set_data( GTK_OBJECT(win_open), "entry", "entry_file" ); + gtk_widget_show( win_open ); + gdk_window_raise( win_open->window ); +} + + +static void on_settings_darea_expose_event_callback( GtkWidget *widget, GdkEventExpose *event, gpointer data ) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(widget) ); + char label[1024]; + + int i; + uint8_t *rgba; + + GtkWidget *optionmenu_title = lookup_widget( hb_win_main, "optionmenu_title" ); + HBTitle *title; + + title = HBListItemAt( hb_status->titleList, gtk_option_menu_get_history( GTK_OPTION_MENU(optionmenu_title) ) ); + title->deinterlace = b_settings_deinterlace; + title->outWidth = i_settings_width; + + title->topCrop = i_settings_crop_top; + title->bottomCrop = i_settings_crop_bottom; + title->leftCrop = i_settings_crop_left; + title->rightCrop = i_settings_crop_right; + + rgba = HBGetPreview( hb_handle, title, i_settings_preview_picture ); + + if( title->outWidth != i_settings_width || + title->topCrop != i_settings_crop_top || + title->bottomCrop != i_settings_crop_bottom || + title->leftCrop != i_settings_crop_left || + title->rightCrop != i_settings_crop_right ) + { + i_settings_width = title->outWidth; + + i_settings_crop_top = title->topCrop; + i_settings_crop_bottom = title->bottomCrop; + i_settings_crop_left = title->leftCrop; + i_settings_crop_right = title->rightCrop; + + gtk_spin_button_set_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_width")), i_settings_width ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_crop_top")), i_settings_crop_top ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_crop_bottom")), i_settings_crop_bottom ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_crop_left")), i_settings_crop_left ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_crop_right")), i_settings_crop_right ); + } + + sprintf( label, "Final size: %dx%d", title->outWidth, title->outHeight ); + gtk_label_set_text( GTK_LABEL(lookup_widget(win, "label_settings")), label ); + + /* FIXME do that only under x86 */ + for( i = 0; i < (title->outWidthMax + 2)*(title->outHeightMax + 2); i++ ) + { + const uint8_t r = rgba[4*i+2]; + const uint8_t g = rgba[4*i+1]; + const uint8_t b = rgba[4*i+0]; + const uint8_t a = rgba[4*i+3]; + + rgba[4*i+0] = r; + rgba[4*i+1] = g; + rgba[4*i+2] = b; + rgba[4*i+3] = a; + } + gdk_draw_rgb_32_image( widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], + 0, 0, title->outWidthMax + 2, title->outHeightMax + 2, + GDK_RGB_DITHER_MAX, + rgba, + (title->outWidthMax+2) * 4 ); + + free( rgba ); +} + +void on_spinbutton_width_value_changed( GtkSpinButton *spinbutton, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(spinbutton) ); + + g_print( "on_spinbutton_width_value_changed\n" ); + + i_settings_width = gtk_spin_button_get_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_width")) ); + + gtk_widget_queue_draw( lookup_widget(win, "drawingarea" ) ); + +} +/* + * FIXME use only one callback + */ +void +on_spinbutton_crop_top_value_changed (GtkSpinButton *spinbutton, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(spinbutton) ); + + i_settings_crop_top = gtk_spin_button_get_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_crop_top")) ); + + gtk_widget_queue_draw( lookup_widget(win, "drawingarea" ) ); +} + + +void +on_spinbutton_crop_bottom_value_changed + (GtkSpinButton *spinbutton, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(spinbutton) ); + + i_settings_crop_bottom = gtk_spin_button_get_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_crop_bottom")) ); + + gtk_widget_queue_draw( lookup_widget(win, "drawingarea" ) ); +} + + +void +on_spinbutton_crop_left_value_changed (GtkSpinButton *spinbutton, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(spinbutton) ); + + i_settings_crop_left = gtk_spin_button_get_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_crop_left")) ); + + gtk_widget_queue_draw( lookup_widget(win, "drawingarea" ) ); +} + + +void +on_spinbutton_crop_right_value_changed (GtkSpinButton *spinbutton, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(spinbutton) ); + + i_settings_crop_right = gtk_spin_button_get_value( GTK_SPIN_BUTTON(lookup_widget(win, "spinbutton_crop_right")) ); + + gtk_widget_queue_draw( lookup_widget(win, "drawingarea" ) ); +} + + +void on_button_settings_clicked( GtkButton *button, + gpointer user_data) +{ + GtkWidget *optionmenu_title = lookup_widget( hb_win_main, "optionmenu_title" ); + HBTitle *title; + + GtkWidget *settings = create_win_settings(); + GtkWidget *darea = lookup_widget( settings, "drawingarea" ); + + title = HBListItemAt( hb_status->titleList, gtk_option_menu_get_history( GTK_OPTION_MENU(optionmenu_title) ) ); + + i_settings_preview_picture = 0; + + gtk_widget_set_size_request( darea, title->outWidthMax + 2, title->outHeightMax + 2 ); + + g_signal_connect (G_OBJECT(darea), "expose_event", + G_CALLBACK (on_settings_darea_expose_event_callback), NULL); + + gtk_spin_button_set_value( GTK_SPIN_BUTTON(lookup_widget(settings, "spinbutton_width")), title->outWidth ); + + gtk_widget_show( settings ); +} + +static void DisplayError( char *title, char *msg ) +{ + GtkWidget *dialog; + + dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + "<b>%s</b>\n\n%s", title, msg ); + gtk_label_set_use_markup( GTK_LABEL( GTK_MESSAGE_DIALOG(dialog)->label), TRUE ); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK ); + gtk_window_set_modal( GTK_WINDOW(dialog), TRUE ); + gtk_dialog_run( GTK_DIALOG(dialog) ); + gtk_widget_destroy( dialog ); +} + +void on_button_start_clicked( GtkButton *button, + gpointer user_data) +{ + int i; + + if( hb_status->i_state != HB_STATE_ENCODING ) + { + GtkWidget *optionmenu_title = lookup_widget( hb_win_main, "optionmenu_title" ); + GtkWidget *widget; + HBTitle *title = HBListItemAt( hb_status->titleList, gtk_option_menu_get_history( GTK_OPTION_MENU(optionmenu_title) ) ); + + int i_ab; + + widget = lookup_widget( hb_win_main, "entry_file" ); + title->file = strdup( gtk_entry_get_text( GTK_ENTRY(widget) ) ); + + if( title->file == NULL || *title->file == '\0' ) + { + DisplayError( "Missing parameters", "You need to specify a file" ); + return; + } + + widget = lookup_widget( hb_win_main, "checkbutton_2pass" ); + title->twoPass = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget) ); + + title->deinterlace = b_settings_deinterlace; + + title->outWidth = i_settings_width; + + title->topCrop = i_settings_crop_top; + title->bottomCrop = i_settings_crop_bottom; + title->leftCrop = i_settings_crop_left; + title->rightCrop = i_settings_crop_right; + + widget = lookup_widget( hb_win_main, "radiobutton_cbitrate" ); + if( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON( widget ) ) ) + { + widget = lookup_widget( hb_win_main, "spinbutton_bitrate" ); + title->bitrate = gtk_spin_button_get_value( GTK_SPIN_BUTTON( widget ) ); + } + else + { + int i_size; + widget = lookup_widget( hb_win_main, "spinbutton_size" ); + i_size = gtk_spin_button_get_value( GTK_SPIN_BUTTON( widget ) ); + + /* FIXME FIXME target size FIXME FIXME */ + title->bitrate = 1024; + /* FIXME */ + } + + widget = lookup_widget( hb_win_main, "optionmenu_codec" ); + switch( gtk_option_menu_get_history( GTK_OPTION_MENU(widget) ) ) + { + case 0: + title->codec = HB_CODEC_FFMPEG; + break; + case 1: + title->codec = HB_CODEC_XVID; + break; + case 2: + title->codec = HB_CODEC_X264; + break; + } + + widget = lookup_widget( hb_win_main, "optionmenu_format" ); + switch( gtk_option_menu_get_history( GTK_OPTION_MENU(widget) ) ) + { + case 0: + { + /* Auto detect */ + char *p = strrchr( title->file, '.' ); + if( p && !strcasecmp( p, ".avi" ) ) + { + title->mux = HB_MUX_AVI; + } + else if( p && !strcasecmp( p, ".mp4" ) ) + { + title->mux = HB_MUX_MP4; + } + else if( p && !strcasecmp( p, ".ogm" ) ) + { + title->mux = HB_MUX_OGM; + } + else + { + title->mux = HB_MUX_AVI; + } + break; + } + case 1: + title->mux = HB_MUX_AVI; + break; + case 2: + title->mux = HB_MUX_MP4; + break; + case 3: + title->mux = HB_MUX_OGM; + break; + } + + /* audio */ + widget = lookup_widget( hb_win_main, "optionmenu_bitrate" ); + switch( gtk_option_menu_get_history( GTK_OPTION_MENU(widget) ) ) + { + case 0: + i_ab = 64; + break; + case 1: + i_ab = 92; + break; + case 2: + i_ab = 128; + break; + case 3: + i_ab = 160; + break; + case 4: + i_ab = 192; + break; + case 5: + i_ab = 256; + break; + case 6: + default: + i_ab = 320; + break; + + } + + HBListInit( &title->ripAudioList ); + widget = lookup_widget( hb_win_main, "optionmenu_language" ); + if( ( i = gtk_option_menu_get_history( GTK_OPTION_MENU(widget) ) ) > 0 ) + { + HBAudio *audio = HBListItemAt( title->audioList, i - 1 ); + + audio->outBitrate = i_ab; + if( title->mux == HB_MUX_AVI ) + { + audio->codec = HB_CODEC_MP3; + } + else if( title->mux == HB_MUX_MP4 ) + { + audio->codec = HB_CODEC_AAC; + } + else if( title->mux == HB_MUX_OGM ) + { + audio->codec = HB_CODEC_VORBIS; + } + HBListAdd( title->ripAudioList, audio ); + } + + widget = lookup_widget( hb_win_main, "optionmenu_language2" ); + if( ( i = gtk_option_menu_get_history( GTK_OPTION_MENU(widget) ) ) > 0 ) + { + HBAudio *audio = HBListItemAt( title->audioList, i - 1 ); + + audio->outBitrate = i_ab; + if( title->mux == HB_MUX_AVI ) + { + audio->codec = HB_CODEC_MP3; + } + else if( title->mux == HB_MUX_MP4 ) + { + audio->codec = HB_CODEC_AAC; + } + else if( title->mux == HB_MUX_OGM ) + { + audio->codec = HB_CODEC_VORBIS; + } + HBListAdd( title->ripAudioList, audio ); + } + HBStartRip( hb_handle, title ); + } + else if( hb_status->i_state == HB_STATE_ENCODING ) + { + HBStopRip( hb_handle ); + } +} + + +void on_entry_file_activate( GtkEntry *entry, + gpointer user_data) +{ +#if 0 + GtkWidget *widget = lookup_widget( hb_win_main, "button_start" ); + char *psz_file = gtk_entry_get_text( entry ); + + if( psz_file && *psz_file ) + { + gtk_widget_set_sensitive( widget, TRUE ); + } + else + { + gtk_widget_set_sensitive( widget, FALSE ); + } +#endif +} + + +static void SettingsUpdate( GtkWidget *win ) +{ + b_settings_deinterlace = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(lookup_widget(win, "checkbutton_deinterlace")) ); +} + +gboolean on_win_settings_delete_event( GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET (widget) ); + + SettingsUpdate( win ); + gtk_widget_destroy( win ); + + return FALSE; +} + + +void on_button_ok_settings_clicked( GtkButton *button, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(button) ); + + SettingsUpdate( win ); + + gtk_widget_destroy( win ); +} + + +void on_button_settings_next_clicked( GtkButton *button, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(button) ); + + if( i_settings_preview_picture < 9 ) + { + i_settings_preview_picture++; + gtk_widget_queue_draw( lookup_widget(win, "drawingarea" ) ); + } + + if( i_settings_preview_picture == 9 ) + { + gtk_widget_set_sensitive( lookup_widget(win, "button_settings_next"), FALSE ); + } + if( i_settings_preview_picture > 0 ) + { + gtk_widget_set_sensitive( lookup_widget(win, "button_settings_previous"), TRUE ); + } +} + + +void on_button_settings_previous_clicked( GtkButton *button, + gpointer user_data) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(button) ); + + if( i_settings_preview_picture > 0 ) + { + i_settings_preview_picture--; + gtk_widget_queue_draw( lookup_widget(win, "drawingarea" ) ); + } + + if( i_settings_preview_picture < 9 ) + { + gtk_widget_set_sensitive( lookup_widget(win, "button_settings_next"), TRUE ); + } + if( i_settings_preview_picture == 0 ) + { + gtk_widget_set_sensitive( lookup_widget(win, "button_settings_previous"), FALSE ); + } +} + + +void on_checkbutton_deinterlace_toggled( GtkToggleButton *togglebutton, + gpointer user_data ) +{ + GtkWidget *win = gtk_widget_get_toplevel( GTK_WIDGET(togglebutton) ); + b_settings_deinterlace = gtk_toggle_button_get_active( togglebutton ); + gtk_widget_queue_draw( lookup_widget(win, "drawingarea" ) ); +} + + diff --git a/gtk2/callbacks.h b/gtk2/callbacks.h new file mode 100644 index 000000000..7040f3567 --- /dev/null +++ b/gtk2/callbacks.h @@ -0,0 +1,75 @@ +#include <gtk/gtk.h> + +extern GtkWidget *hb_win_main; +extern HBHandle *hb_handle; +extern HBStatus *hb_status; + +gboolean on_win_main_delete_event( GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +gboolean on_win_open_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + + +void on_button_browse_device (GtkButton *button, + gpointer user_data); + +void on_ok_button1_clicked (GtkButton *button, + gpointer user_data); + +void on_cancel_button1_clicked (GtkButton *button, + gpointer user_data); + +void on_entry_device_activate (GtkEntry *entry, + gpointer user_data); + +void on_optionmenu_title_changed (GtkOptionMenu *optionmenu, + gpointer user_data); + +void on_button_browse_file_clicked (GtkButton *button, + gpointer user_data); + +void on_button_settings_clicked (GtkButton *button, + gpointer user_data); + +void on_button_start_clicked (GtkButton *button, + gpointer user_data); + +void on_entry_file_activate (GtkEntry *entry, + gpointer user_data); + +gboolean on_win_settings_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void on_button_ok_settings_clicked (GtkButton *button, + gpointer user_data); + +void on_button_settings_next_clicked (GtkButton *button, + gpointer user_data); + +void on_button_settings_previous_clicked (GtkButton *button, + gpointer user_data); + +void on_checkbutton_deinterlace_toggled (GtkToggleButton *togglebutton, + gpointer user_data); +void on_spinbutton_width_value_changed( GtkSpinButton *spinbutton, + gpointer user_data); + +void on_spinbutton_crop_top_value_changed (GtkSpinButton *spinbutton, + gpointer user_data); + +void on_spinbutton_crop_bottom_value_changed + (GtkSpinButton *spinbutton, + gpointer user_data); + +void +on_spinbutton_crop_left_value_changed (GtkSpinButton *spinbutton, + gpointer user_data); + +void +on_spinbutton_crop_right_value_changed (GtkSpinButton *spinbutton, + gpointer user_data); + diff --git a/gtk2/gtk2hb.glade b/gtk2/gtk2hb.glade new file mode 100644 index 000000000..50b3e81cd --- /dev/null +++ b/gtk2/gtk2hb.glade @@ -0,0 +1,1863 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="win_main"> + <property name="visible">True</property> + <property name="title" translatable="yes">HandBrake</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <signal name="delete_event" handler="on_win_main_delete_event" last_modification_time="Fri, 05 Dec 2003 23:54:16 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkFrame" id="frame_dvd"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkVBox" id="vbox11"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkAlignment" id="alignment13"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">1</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Device </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkCombo" id="combo1"> + <property name="visible">True</property> + <property name="value_in_list">False</property> + <property name="allow_empty">True</property> + <property name="case_sensitive">False</property> + <property name="enable_arrow_keys">True</property> + <property name="enable_arrows_always">False</property> + + <child internal-child="entry"> + <widget class="GtkEntry" id="entry_device"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <signal name="activate" handler="on_entry_device_activate" last_modification_time="Sat, 06 Dec 2003 02:59:59 GMT"/> + </widget> + </child> + + <child internal-child="list"> + <widget class="GtkList" id="combo-list1"> + <property name="visible">True</property> + <property name="selection_mode">GTK_SELECTION_BROWSE</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button_browse_device"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_button_browse_device" last_modification_time="Sat, 06 Dec 2003 02:19:48 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">Browse</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes">DVD</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox_parameters"> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkFrame" id="frame_video"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkHBox" id="hbox18"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkAlignment" id="alignment7"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkVBox" id="vbox7"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label13"> + <property name="visible">True</property> + <property name="label" translatable="yes">Title</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label12"> + <property name="visible">True</property> + <property name="label" translatable="yes">Codec</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="radiobutton_cbitrate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Custom bitrate</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">True</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="radiobutton_tsize"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Target size</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">radiobutton_cbitrate</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="checkbutton_2pass"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">2-pass encoding</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">True</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment8"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkVBox" id="vbox8"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkOptionMenu" id="optionmenu_title"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="history">-1</property> + <signal name="changed" handler="on_optionmenu_title_changed" last_modification_time="Sat, 06 Dec 2003 04:23:30 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkOptionMenu" id="optionmenu_codec"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child> + <widget class="GtkMenu" id="menu_codec"> + + <child> + <widget class="GtkMenuItem" id="mpeg-4_(ffmpeg)1"> + <property name="visible">True</property> + <property name="label" translatable="yes">MPEG-4 (FFmpeg)</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="mpeg-4_(xvid)1"> + <property name="visible">True</property> + <property name="label" translatable="yes">MPEG-4 (XviD)</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="h264_(x264)1"> + <property name="visible">True</property> + <property name="label" translatable="yes">H264 (x264)</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="spinbutton_bitrate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">False</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">1024 100 5000 1 10 10</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="spinbutton_size"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">False</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">700 0 2000 1 10 10</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button_settings"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Crop & Resize..</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_button_settings_clicked" last_modification_time="Sat, 06 Dec 2003 05:00:14 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Video</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame_audio"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkHBox" id="hbox19"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkAlignment" id="alignment9"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkVBox" id="vbox9"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label14"> + <property name="visible">True</property> + <property name="label" translatable="yes">Language</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label15"> + <property name="visible">True</property> + <property name="label" translatable="yes">Secondary language</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label16"> + <property name="visible">True</property> + <property name="label" translatable="yes">Bitrate</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment10"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkVBox" id="vbox10"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkOptionMenu" id="optionmenu_language"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="history">-1</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkOptionMenu" id="optionmenu_language2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="history">-1</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkOptionMenu" id="optionmenu_bitrate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child> + <widget class="GtkMenu" id="menu1"> + + <child> + <widget class="GtkMenuItem" id="2"> + <property name="visible">True</property> + <property name="label" translatable="yes">64</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="4"> + <property name="visible">True</property> + <property name="label" translatable="yes">96</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="7"> + <property name="visible">True</property> + <property name="label" translatable="yes">128</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="10"> + <property name="visible">True</property> + <property name="label" translatable="yes">160</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="11"> + <property name="visible">True</property> + <property name="label" translatable="yes">192</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="12"> + <property name="visible">True</property> + <property name="label" translatable="yes">256</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="13"> + <property name="visible">True</property> + <property name="label" translatable="yes">320</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="label" translatable="yes">Audio</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame_output"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHBox" id="hbox20"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkAlignment" id="alignment11"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkLabel" id="label17"> + <property name="visible">True</property> + <property name="label" translatable="yes">Format</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment12"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + + <child> + <widget class="GtkOptionMenu" id="optionmenu_format"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="history">0</property> + + <child> + <widget class="GtkMenu" id="menu2"> + + <child> + <widget class="GtkMenuItem" id="auto1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Auto</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="avi1"> + <property name="visible">True</property> + <property name="label" translatable="yes">AVI</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="mp1"> + <property name="visible">True</property> + <property name="label" translatable="yes">MP4</property> + <property name="use_underline">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="ogm1"> + <property name="visible">True</property> + <property name="label" translatable="yes">OGM</property> + <property name="use_underline">True</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox6"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label18"> + <property name="visible">True</property> + <property name="label" translatable="yes">File </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkCombo" id="combo2"> + <property name="visible">True</property> + <property name="value_in_list">False</property> + <property name="allow_empty">True</property> + <property name="case_sensitive">False</property> + <property name="enable_arrow_keys">True</property> + <property name="enable_arrows_always">False</property> + + <child internal-child="entry"> + <widget class="GtkEntry" id="entry_file"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <signal name="activate" handler="on_entry_file_activate" last_modification_time="Sat, 06 Dec 2003 05:04:29 GMT"/> + </widget> + </child> + + <child internal-child="list"> + <widget class="GtkList" id="list1"> + <property name="visible">True</property> + <property name="selection_mode">GTK_SELECTION_BROWSE</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button_browse_file"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_button_browse_file_clicked" last_modification_time="Sat, 06 Dec 2003 04:52:12 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox7"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label19"> + <property name="visible">True</property> + <property name="label" translatable="yes">Browse</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes">Output</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">6</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkButton" id="button_start"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_button_start_clicked" last_modification_time="Sat, 06 Dec 2003 04:59:15 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment3"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox9"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="button_start_image"> + <property name="visible">True</property> + <property name="stock">gtk-apply</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="button_start_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Start</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">4</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox10"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkProgressBar" id="progressbar"> + <property name="visible">True</property> + <property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property> + <property name="fraction">0</property> + <property name="pulse_step">0.1</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkStatusbar" id="statusbar"> + <property name="visible">True</property> + <property name="has_resize_grip">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkFileSelection" id="win_open"> + <property name="border_width">10</property> + <property name="visible">True</property> + <property name="title" translatable="yes">Select File</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="show_fileops">True</property> + <signal name="delete_event" handler="on_win_open_delete_event" last_modification_time="Sat, 06 Dec 2003 00:17:21 GMT"/> + + <child internal-child="cancel_button"> + <widget class="GtkButton" id="cancel_button1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_cancel_button1_clicked" last_modification_time="Sat, 06 Dec 2003 00:17:46 GMT"/> + </widget> + </child> + + <child internal-child="ok_button"> + <widget class="GtkButton" id="ok_button1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_ok_button1_clicked" last_modification_time="Sat, 06 Dec 2003 00:17:56 GMT"/> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="win_settings"> + <property name="visible">True</property> + <property name="title" translatable="yes">Picture settings</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <signal name="delete_event" handler="on_win_settings_delete_event" last_modification_time="Sat, 06 Dec 2003 19:07:23 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkDrawingArea" id="drawingarea"> + <property name="visible">True</property> + </widget> + <packing> + <property name="padding">10</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table5"> + <property name="visible">True</property> + <property name="n_rows">1</property> + <property name="n_columns">3</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHButtonBox" id="hbuttonbox2"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkButton" id="button_settings_previous"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_button_settings_previous_clicked" last_modification_time="Sat, 06 Dec 2003 20:58:51 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment5"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox12"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image7"> + <property name="visible">True</property> + <property name="stock">gtk-go-back</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label22"> + <property name="visible">True</property> + <property name="label" translatable="yes">Previous</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button_settings_next"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_button_settings_next_clicked" last_modification_time="Sat, 06 Dec 2003 20:51:27 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment6"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox13"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image8"> + <property name="visible">True</property> + <property name="stock">gtk-go-forward</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label23"> + <property name="visible">True</property> + <property name="label" translatable="yes">Next</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHBox" id="hbox17"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkTable" id="table8"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">3</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkSpinButton" id="spinbutton_width"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">True</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">0 0 4096 16 16 10</property> + <signal name="value_changed" handler="on_spinbutton_width_value_changed" last_modification_time="Sun, 07 Dec 2003 23:24:59 GMT"/> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="spinbutton_crop_top"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">False</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">0 0 4096 2 10 10</property> + <signal name="value_changed" handler="on_spinbutton_crop_top_value_changed" last_modification_time="Sun, 07 Dec 2003 23:42:52 GMT"/> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label26"> + <property name="visible">True</property> + <property name="label" translatable="yes">Bottom crop</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label25"> + <property name="visible">True</property> + <property name="label" translatable="yes">Top crop</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label24"> + <property name="visible">True</property> + <property name="label" translatable="yes">Picture width</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="spinbutton_crop_bottom"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">False</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">0 0 4096 2 10 10</property> + <signal name="value_changed" handler="on_spinbutton_crop_bottom_value_changed" last_modification_time="Sun, 07 Dec 2003 23:43:06 GMT"/> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table9"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">3</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkSpinButton" id="spinbutton_crop_left"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">False</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">0 0 4096 2 10 10</property> + <signal name="value_changed" handler="on_spinbutton_crop_left_value_changed" last_modification_time="Sun, 07 Dec 2003 23:43:30 GMT"/> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label28"> + <property name="visible">True</property> + <property name="label" translatable="yes">Right crop</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label27"> + <property name="visible">True</property> + <property name="label" translatable="yes">Left crop</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkSpinButton" id="spinbutton_crop_right"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="climb_rate">1</property> + <property name="digits">0</property> + <property name="numeric">False</property> + <property name="update_policy">GTK_UPDATE_ALWAYS</property> + <property name="snap_to_ticks">False</property> + <property name="wrap">False</property> + <property name="adjustment">0 0 4096 2 10 10</property> + <signal name="value_changed" handler="on_spinbutton_crop_right_value_changed" last_modification_time="Sun, 07 Dec 2003 23:43:42 GMT"/> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="checkbutton_deinterlace"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">deinterlace</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_checkbutton_deinterlace_toggled" last_modification_time="Sat, 06 Dec 2003 21:12:08 GMT"/> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHSeparator" id="hseparator1"> + <property name="visible">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="table4"> + <property name="visible">True</property> + <property name="n_rows">1</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">0</property> + <property name="column_spacing">0</property> + + <child> + <widget class="GtkButton" id="button1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_button_ok_settings_clicked" last_modification_time="Sat, 06 Dec 2003 19:07:02 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment4"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox11"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image5"> + <property name="visible">True</property> + <property name="stock">gtk-apply</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label20"> + <property name="visible">True</property> + <property name="label" translatable="yes">Ok</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label_settings"> + <property name="visible">True</property> + <property name="label" translatable="yes">label21</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/gtk2/interface.c b/gtk2/interface.c new file mode 100644 index 000000000..826889c31 --- /dev/null +++ b/gtk2/interface.c @@ -0,0 +1,984 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include "HandBrake.h" +#include "status.h" +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +GtkWidget* +create_win_main (void) +{ + GtkWidget *win_main; + GtkWidget *vbox1; + GtkWidget *frame_dvd; + GtkWidget *vbox11; + GtkWidget *alignment13; + GtkWidget *hbox1; + GtkWidget *label3; + GtkWidget *combo1; + GtkWidget *entry_device; + GtkWidget *button_browse_device; + GtkWidget *alignment1; + GtkWidget *hbox2; + GtkWidget *image1; + GtkWidget *label4; + GtkWidget *label1; + GtkWidget *vbox_parameters; + GtkWidget *frame_video; + GtkWidget *hbox18; + GtkWidget *alignment7; + GtkWidget *vbox7; + GtkWidget *label13; + GtkWidget *label12; + GtkWidget *radiobutton_cbitrate; + GSList *radiobutton_cbitrate_group = NULL; + GtkWidget *radiobutton_tsize; + GtkWidget *checkbutton_2pass; + GtkWidget *alignment8; + GtkWidget *vbox8; + GtkWidget *optionmenu_title; + GtkWidget *optionmenu_codec; + GtkWidget *menu_codec; + GtkWidget *mpeg_4__ffmpeg_1; + GtkWidget *mpeg_4__xvid_1; + GtkWidget *h264__x264_1; + GtkObject *spinbutton_bitrate_adj; + GtkWidget *spinbutton_bitrate; + GtkObject *spinbutton_size_adj; + GtkWidget *spinbutton_size; + GtkWidget *button_settings; + GtkWidget *label6; + GtkWidget *frame_audio; + GtkWidget *hbox19; + GtkWidget *alignment9; + GtkWidget *vbox9; + GtkWidget *label14; + GtkWidget *label15; + GtkWidget *label16; + GtkWidget *alignment10; + GtkWidget *vbox10; + GtkWidget *optionmenu_language; + GtkWidget *optionmenu_language2; + GtkWidget *optionmenu_bitrate; + GtkWidget *menu1; + GtkWidget *_2; + GtkWidget *_4; + GtkWidget *_7; + GtkWidget *_10; + GtkWidget *_11; + GtkWidget *_12; + GtkWidget *_13; + GtkWidget *label8; + GtkWidget *frame_output; + GtkWidget *vbox2; + GtkWidget *hbox20; + GtkWidget *alignment11; + GtkWidget *label17; + GtkWidget *alignment12; + GtkWidget *optionmenu_format; + GtkWidget *menu2; + GtkWidget *auto1; + GtkWidget *avi1; + GtkWidget *mp1; + GtkWidget *ogm1; + GtkWidget *hbox6; + GtkWidget *label18; + GtkWidget *combo2; + GtkWidget *entry_file; + GtkWidget *button_browse_file; + GtkWidget *alignment2; + GtkWidget *hbox7; + GtkWidget *image4; + GtkWidget *label19; + GtkWidget *label9; + GtkWidget *hbuttonbox1; + GtkWidget *button_start; + GtkWidget *alignment3; + GtkWidget *hbox9; + GtkWidget *button_start_image; + GtkWidget *button_start_label; + GtkWidget *hbox10; + GtkWidget *progressbar; + GtkWidget *statusbar; + + win_main = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (win_main), "HandBrake"); + + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox1); + gtk_container_add (GTK_CONTAINER (win_main), vbox1); + + frame_dvd = gtk_frame_new (NULL); + gtk_widget_show (frame_dvd); + gtk_box_pack_start (GTK_BOX (vbox1), frame_dvd, TRUE, TRUE, 0); + + vbox11 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox11); + gtk_container_add (GTK_CONTAINER (frame_dvd), vbox11); + gtk_container_set_border_width (GTK_CONTAINER (vbox11), 5); + + alignment13 = gtk_alignment_new (0, 1, 1, 1); + gtk_widget_show (alignment13); + gtk_box_pack_start (GTK_BOX (vbox11), alignment13, TRUE, FALSE, 0); + + hbox1 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox1); + gtk_container_add (GTK_CONTAINER (alignment13), hbox1); + + label3 = gtk_label_new ("Device "); + gtk_widget_show (label3); + gtk_box_pack_start (GTK_BOX (hbox1), label3, FALSE, TRUE, 0); + + combo1 = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo1)->popwin), + "GladeParentKey", combo1); + gtk_widget_show (combo1); + gtk_box_pack_start (GTK_BOX (hbox1), combo1, TRUE, TRUE, 0); + + entry_device = GTK_COMBO (combo1)->entry; + gtk_widget_show (entry_device); + + button_browse_device = gtk_button_new (); + gtk_widget_show (button_browse_device); + gtk_box_pack_start (GTK_BOX (hbox1), button_browse_device, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (button_browse_device, GTK_CAN_DEFAULT); + + alignment1 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment1); + gtk_container_add (GTK_CONTAINER (button_browse_device), alignment1); + + hbox2 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox2); + gtk_container_add (GTK_CONTAINER (alignment1), hbox2); + + image1 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image1); + gtk_box_pack_start (GTK_BOX (hbox2), image1, FALSE, FALSE, 0); + + label4 = gtk_label_new_with_mnemonic ("Browse"); + gtk_widget_show (label4); + gtk_box_pack_start (GTK_BOX (hbox2), label4, FALSE, FALSE, 0); + + label1 = gtk_label_new ("DVD"); + gtk_widget_show (label1); + gtk_frame_set_label_widget (GTK_FRAME (frame_dvd), label1); + + vbox_parameters = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox1), vbox_parameters, FALSE, TRUE, 0); + + frame_video = gtk_frame_new (NULL); + gtk_widget_show (frame_video); + gtk_box_pack_start (GTK_BOX (vbox_parameters), frame_video, FALSE, TRUE, 0); + + hbox18 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox18); + gtk_container_add (GTK_CONTAINER (frame_video), hbox18); + gtk_container_set_border_width (GTK_CONTAINER (hbox18), 5); + + alignment7 = gtk_alignment_new (0, 0.5, 1, 1); + gtk_widget_show (alignment7); + gtk_box_pack_start (GTK_BOX (hbox18), alignment7, TRUE, TRUE, 0); + + vbox7 = gtk_vbox_new (TRUE, 0); + gtk_widget_show (vbox7); + gtk_container_add (GTK_CONTAINER (alignment7), vbox7); + + label13 = gtk_label_new ("Title"); + gtk_widget_show (label13); + gtk_box_pack_start (GTK_BOX (vbox7), label13, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label13), 0, 0.5); + + label12 = gtk_label_new ("Codec"); + gtk_widget_show (label12); + gtk_box_pack_start (GTK_BOX (vbox7), label12, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label12), 0, 0.5); + + radiobutton_cbitrate = gtk_radio_button_new_with_mnemonic (NULL, "Custom bitrate"); + gtk_widget_show (radiobutton_cbitrate); + gtk_box_pack_start (GTK_BOX (vbox7), radiobutton_cbitrate, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton_cbitrate), radiobutton_cbitrate_group); + radiobutton_cbitrate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton_cbitrate)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radiobutton_cbitrate), TRUE); + + radiobutton_tsize = gtk_radio_button_new_with_mnemonic (NULL, "Target size"); + gtk_widget_show (radiobutton_tsize); + gtk_box_pack_start (GTK_BOX (vbox7), radiobutton_tsize, FALSE, FALSE, 0); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (radiobutton_tsize), radiobutton_cbitrate_group); + radiobutton_cbitrate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radiobutton_tsize)); + + checkbutton_2pass = gtk_check_button_new_with_mnemonic ("2-pass encoding"); + gtk_widget_show (checkbutton_2pass); + gtk_box_pack_start (GTK_BOX (vbox7), checkbutton_2pass, FALSE, FALSE, 0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton_2pass), TRUE); + + alignment8 = gtk_alignment_new (1, 0.5, 1, 1); + gtk_widget_show (alignment8); + gtk_box_pack_start (GTK_BOX (hbox18), alignment8, TRUE, TRUE, 0); + + vbox8 = gtk_vbox_new (TRUE, 0); + gtk_widget_show (vbox8); + gtk_container_add (GTK_CONTAINER (alignment8), vbox8); + + optionmenu_title = gtk_option_menu_new (); + gtk_widget_show (optionmenu_title); + gtk_box_pack_start (GTK_BOX (vbox8), optionmenu_title, FALSE, FALSE, 0); + + optionmenu_codec = gtk_option_menu_new (); + gtk_widget_show (optionmenu_codec); + gtk_box_pack_start (GTK_BOX (vbox8), optionmenu_codec, FALSE, FALSE, 0); + + menu_codec = gtk_menu_new (); + + mpeg_4__ffmpeg_1 = gtk_menu_item_new_with_mnemonic ("MPEG-4 (FFmpeg)"); + gtk_widget_show (mpeg_4__ffmpeg_1); + gtk_container_add (GTK_CONTAINER (menu_codec), mpeg_4__ffmpeg_1); + + mpeg_4__xvid_1 = gtk_menu_item_new_with_mnemonic ("MPEG-4 (XviD)"); + gtk_widget_show (mpeg_4__xvid_1); + gtk_container_add (GTK_CONTAINER (menu_codec), mpeg_4__xvid_1); + + h264__x264_1 = gtk_menu_item_new_with_mnemonic ("H264 (x264)"); + gtk_widget_show (h264__x264_1); + gtk_container_add (GTK_CONTAINER (menu_codec), h264__x264_1); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu_codec), menu_codec); + + spinbutton_bitrate_adj = gtk_adjustment_new (1024, 100, 5000, 1, 10, 10); + spinbutton_bitrate = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_bitrate_adj), 1, 0); + gtk_widget_show (spinbutton_bitrate); + gtk_box_pack_start (GTK_BOX (vbox8), spinbutton_bitrate, FALSE, FALSE, 0); + + spinbutton_size_adj = gtk_adjustment_new (700, 0, 2000, 1, 10, 10); + spinbutton_size = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_size_adj), 1, 0); + gtk_widget_show (spinbutton_size); + gtk_box_pack_start (GTK_BOX (vbox8), spinbutton_size, FALSE, FALSE, 0); + + button_settings = gtk_button_new_with_mnemonic ("Crop & Resize.."); + gtk_widget_show (button_settings); + gtk_box_pack_start (GTK_BOX (vbox8), button_settings, FALSE, FALSE, 0); + + label6 = gtk_label_new ("Video"); + gtk_widget_show (label6); + gtk_frame_set_label_widget (GTK_FRAME (frame_video), label6); + + frame_audio = gtk_frame_new (NULL); + gtk_widget_show (frame_audio); + gtk_box_pack_start (GTK_BOX (vbox_parameters), frame_audio, FALSE, TRUE, 0); + + hbox19 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox19); + gtk_container_add (GTK_CONTAINER (frame_audio), hbox19); + gtk_container_set_border_width (GTK_CONTAINER (hbox19), 5); + + alignment9 = gtk_alignment_new (0, 0.5, 1, 1); + gtk_widget_show (alignment9); + gtk_box_pack_start (GTK_BOX (hbox19), alignment9, TRUE, TRUE, 0); + + vbox9 = gtk_vbox_new (TRUE, 0); + gtk_widget_show (vbox9); + gtk_container_add (GTK_CONTAINER (alignment9), vbox9); + + label14 = gtk_label_new ("Language"); + gtk_widget_show (label14); + gtk_box_pack_start (GTK_BOX (vbox9), label14, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label14), 0, 0.5); + + label15 = gtk_label_new ("Secondary language"); + gtk_widget_show (label15); + gtk_box_pack_start (GTK_BOX (vbox9), label15, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label15), 0, 0.5); + + label16 = gtk_label_new ("Bitrate"); + gtk_widget_show (label16); + gtk_box_pack_start (GTK_BOX (vbox9), label16, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label16), 0, 0.5); + + alignment10 = gtk_alignment_new (1, 0.5, 1, 1); + gtk_widget_show (alignment10); + gtk_box_pack_start (GTK_BOX (hbox19), alignment10, TRUE, TRUE, 0); + + vbox10 = gtk_vbox_new (TRUE, 0); + gtk_widget_show (vbox10); + gtk_container_add (GTK_CONTAINER (alignment10), vbox10); + + optionmenu_language = gtk_option_menu_new (); + gtk_widget_show (optionmenu_language); + gtk_box_pack_start (GTK_BOX (vbox10), optionmenu_language, FALSE, FALSE, 0); + + optionmenu_language2 = gtk_option_menu_new (); + gtk_widget_show (optionmenu_language2); + gtk_box_pack_start (GTK_BOX (vbox10), optionmenu_language2, FALSE, FALSE, 0); + + optionmenu_bitrate = gtk_option_menu_new (); + gtk_widget_show (optionmenu_bitrate); + gtk_box_pack_start (GTK_BOX (vbox10), optionmenu_bitrate, FALSE, FALSE, 0); + + menu1 = gtk_menu_new (); + + _2 = gtk_menu_item_new_with_mnemonic ("64"); + gtk_widget_show (_2); + gtk_container_add (GTK_CONTAINER (menu1), _2); + + _4 = gtk_menu_item_new_with_mnemonic ("96"); + gtk_widget_show (_4); + gtk_container_add (GTK_CONTAINER (menu1), _4); + + _7 = gtk_menu_item_new_with_mnemonic ("128"); + gtk_widget_show (_7); + gtk_container_add (GTK_CONTAINER (menu1), _7); + + _10 = gtk_menu_item_new_with_mnemonic ("160"); + gtk_widget_show (_10); + gtk_container_add (GTK_CONTAINER (menu1), _10); + + _11 = gtk_menu_item_new_with_mnemonic ("192"); + gtk_widget_show (_11); + gtk_container_add (GTK_CONTAINER (menu1), _11); + + _12 = gtk_menu_item_new_with_mnemonic ("256"); + gtk_widget_show (_12); + gtk_container_add (GTK_CONTAINER (menu1), _12); + + _13 = gtk_menu_item_new_with_mnemonic ("320"); + gtk_widget_show (_13); + gtk_container_add (GTK_CONTAINER (menu1), _13); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu_bitrate), menu1); + + label8 = gtk_label_new ("Audio"); + gtk_widget_show (label8); + gtk_frame_set_label_widget (GTK_FRAME (frame_audio), label8); + + frame_output = gtk_frame_new (NULL); + gtk_widget_show (frame_output); + gtk_box_pack_start (GTK_BOX (vbox_parameters), frame_output, FALSE, TRUE, 6); + + vbox2 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox2); + gtk_container_add (GTK_CONTAINER (frame_output), vbox2); + gtk_container_set_border_width (GTK_CONTAINER (vbox2), 5); + + hbox20 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox20); + gtk_box_pack_start (GTK_BOX (vbox2), hbox20, TRUE, TRUE, 0); + + alignment11 = gtk_alignment_new (0, 0.5, 1, 1); + gtk_widget_show (alignment11); + gtk_box_pack_start (GTK_BOX (hbox20), alignment11, TRUE, TRUE, 0); + + label17 = gtk_label_new ("Format"); + gtk_widget_show (label17); + gtk_container_add (GTK_CONTAINER (alignment11), label17); + gtk_misc_set_alignment (GTK_MISC (label17), 0, 0.5); + + alignment12 = gtk_alignment_new (1, 0.5, 1, 1); + gtk_widget_show (alignment12); + gtk_box_pack_start (GTK_BOX (hbox20), alignment12, TRUE, TRUE, 0); + + optionmenu_format = gtk_option_menu_new (); + gtk_widget_show (optionmenu_format); + gtk_container_add (GTK_CONTAINER (alignment12), optionmenu_format); + + menu2 = gtk_menu_new (); + + auto1 = gtk_menu_item_new_with_mnemonic ("Auto"); + gtk_widget_show (auto1); + gtk_container_add (GTK_CONTAINER (menu2), auto1); + + avi1 = gtk_menu_item_new_with_mnemonic ("AVI"); + gtk_widget_show (avi1); + gtk_container_add (GTK_CONTAINER (menu2), avi1); + + mp1 = gtk_menu_item_new_with_mnemonic ("MP4"); + gtk_widget_show (mp1); + gtk_container_add (GTK_CONTAINER (menu2), mp1); + + ogm1 = gtk_menu_item_new_with_mnemonic ("OGM"); + gtk_widget_show (ogm1); + gtk_container_add (GTK_CONTAINER (menu2), ogm1); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu_format), menu2); + + hbox6 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox6); + gtk_box_pack_start (GTK_BOX (vbox2), hbox6, TRUE, TRUE, 0); + + label18 = gtk_label_new ("File "); + gtk_widget_show (label18); + gtk_box_pack_start (GTK_BOX (hbox6), label18, FALSE, TRUE, 0); + + combo2 = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo2)->popwin), + "GladeParentKey", combo2); + gtk_widget_show (combo2); + gtk_box_pack_start (GTK_BOX (hbox6), combo2, TRUE, TRUE, 0); + + entry_file = GTK_COMBO (combo2)->entry; + gtk_widget_show (entry_file); + + button_browse_file = gtk_button_new (); + gtk_widget_show (button_browse_file); + gtk_box_pack_start (GTK_BOX (hbox6), button_browse_file, FALSE, FALSE, 0); + GTK_WIDGET_SET_FLAGS (button_browse_file, GTK_CAN_DEFAULT); + + alignment2 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment2); + gtk_container_add (GTK_CONTAINER (button_browse_file), alignment2); + + hbox7 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox7); + gtk_container_add (GTK_CONTAINER (alignment2), hbox7); + + image4 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image4); + gtk_box_pack_start (GTK_BOX (hbox7), image4, FALSE, FALSE, 0); + + label19 = gtk_label_new_with_mnemonic ("Browse"); + gtk_widget_show (label19); + gtk_box_pack_start (GTK_BOX (hbox7), label19, FALSE, FALSE, 0); + + label9 = gtk_label_new ("Output"); + gtk_widget_show (label9); + gtk_frame_set_label_widget (GTK_FRAME (frame_output), label9); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox1); + gtk_box_pack_start (GTK_BOX (vbox_parameters), hbuttonbox1, FALSE, TRUE, 4); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_END); + + button_start = gtk_button_new (); + gtk_widget_show (button_start); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button_start); + GTK_WIDGET_SET_FLAGS (button_start, GTK_CAN_DEFAULT); + + alignment3 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment3); + gtk_container_add (GTK_CONTAINER (button_start), alignment3); + + hbox9 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox9); + gtk_container_add (GTK_CONTAINER (alignment3), hbox9); + + button_start_image = gtk_image_new_from_stock ("gtk-apply", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (button_start_image); + gtk_box_pack_start (GTK_BOX (hbox9), button_start_image, FALSE, FALSE, 0); + + button_start_label = gtk_label_new_with_mnemonic ("Start"); + gtk_widget_show (button_start_label); + gtk_box_pack_start (GTK_BOX (hbox9), button_start_label, FALSE, FALSE, 0); + + hbox10 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox10); + gtk_box_pack_start (GTK_BOX (vbox1), hbox10, FALSE, FALSE, 0); + + progressbar = gtk_progress_bar_new (); + gtk_widget_show (progressbar); + gtk_box_pack_start (GTK_BOX (hbox10), progressbar, FALSE, FALSE, 0); + + statusbar = gtk_statusbar_new (); + gtk_widget_show (statusbar); + gtk_box_pack_start (GTK_BOX (hbox10), statusbar, TRUE, TRUE, 0); + + g_signal_connect ((gpointer) win_main, "delete_event", + G_CALLBACK (on_win_main_delete_event), + NULL); + g_signal_connect ((gpointer) entry_device, "activate", + G_CALLBACK (on_entry_device_activate), + NULL); + g_signal_connect ((gpointer) button_browse_device, "clicked", + G_CALLBACK (on_button_browse_device), + NULL); + g_signal_connect ((gpointer) optionmenu_title, "changed", + G_CALLBACK (on_optionmenu_title_changed), + NULL); + g_signal_connect ((gpointer) button_settings, "clicked", + G_CALLBACK (on_button_settings_clicked), + NULL); + g_signal_connect ((gpointer) entry_file, "activate", + G_CALLBACK (on_entry_file_activate), + NULL); + g_signal_connect ((gpointer) button_browse_file, "clicked", + G_CALLBACK (on_button_browse_file_clicked), + NULL); + g_signal_connect ((gpointer) button_start, "clicked", + G_CALLBACK (on_button_start_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (win_main, win_main, "win_main"); + GLADE_HOOKUP_OBJECT (win_main, vbox1, "vbox1"); + GLADE_HOOKUP_OBJECT (win_main, frame_dvd, "frame_dvd"); + GLADE_HOOKUP_OBJECT (win_main, vbox11, "vbox11"); + GLADE_HOOKUP_OBJECT (win_main, alignment13, "alignment13"); + GLADE_HOOKUP_OBJECT (win_main, hbox1, "hbox1"); + GLADE_HOOKUP_OBJECT (win_main, label3, "label3"); + GLADE_HOOKUP_OBJECT (win_main, combo1, "combo1"); + GLADE_HOOKUP_OBJECT (win_main, entry_device, "entry_device"); + GLADE_HOOKUP_OBJECT (win_main, button_browse_device, "button_browse_device"); + GLADE_HOOKUP_OBJECT (win_main, alignment1, "alignment1"); + GLADE_HOOKUP_OBJECT (win_main, hbox2, "hbox2"); + GLADE_HOOKUP_OBJECT (win_main, image1, "image1"); + GLADE_HOOKUP_OBJECT (win_main, label4, "label4"); + GLADE_HOOKUP_OBJECT (win_main, label1, "label1"); + GLADE_HOOKUP_OBJECT (win_main, vbox_parameters, "vbox_parameters"); + GLADE_HOOKUP_OBJECT (win_main, frame_video, "frame_video"); + GLADE_HOOKUP_OBJECT (win_main, hbox18, "hbox18"); + GLADE_HOOKUP_OBJECT (win_main, alignment7, "alignment7"); + GLADE_HOOKUP_OBJECT (win_main, vbox7, "vbox7"); + GLADE_HOOKUP_OBJECT (win_main, label13, "label13"); + GLADE_HOOKUP_OBJECT (win_main, label12, "label12"); + GLADE_HOOKUP_OBJECT (win_main, radiobutton_cbitrate, "radiobutton_cbitrate"); + GLADE_HOOKUP_OBJECT (win_main, radiobutton_tsize, "radiobutton_tsize"); + GLADE_HOOKUP_OBJECT (win_main, checkbutton_2pass, "checkbutton_2pass"); + GLADE_HOOKUP_OBJECT (win_main, alignment8, "alignment8"); + GLADE_HOOKUP_OBJECT (win_main, vbox8, "vbox8"); + GLADE_HOOKUP_OBJECT (win_main, optionmenu_title, "optionmenu_title"); + GLADE_HOOKUP_OBJECT (win_main, optionmenu_codec, "optionmenu_codec"); + GLADE_HOOKUP_OBJECT (win_main, menu_codec, "menu_codec"); + GLADE_HOOKUP_OBJECT (win_main, mpeg_4__ffmpeg_1, "mpeg_4__ffmpeg_1"); + GLADE_HOOKUP_OBJECT (win_main, mpeg_4__xvid_1, "mpeg_4__xvid_1"); + GLADE_HOOKUP_OBJECT (win_main, h264__x264_1, "h264__x264_1"); + GLADE_HOOKUP_OBJECT (win_main, spinbutton_bitrate, "spinbutton_bitrate"); + GLADE_HOOKUP_OBJECT (win_main, spinbutton_size, "spinbutton_size"); + GLADE_HOOKUP_OBJECT (win_main, button_settings, "button_settings"); + GLADE_HOOKUP_OBJECT (win_main, label6, "label6"); + GLADE_HOOKUP_OBJECT (win_main, frame_audio, "frame_audio"); + GLADE_HOOKUP_OBJECT (win_main, hbox19, "hbox19"); + GLADE_HOOKUP_OBJECT (win_main, alignment9, "alignment9"); + GLADE_HOOKUP_OBJECT (win_main, vbox9, "vbox9"); + GLADE_HOOKUP_OBJECT (win_main, label14, "label14"); + GLADE_HOOKUP_OBJECT (win_main, label15, "label15"); + GLADE_HOOKUP_OBJECT (win_main, label16, "label16"); + GLADE_HOOKUP_OBJECT (win_main, alignment10, "alignment10"); + GLADE_HOOKUP_OBJECT (win_main, vbox10, "vbox10"); + GLADE_HOOKUP_OBJECT (win_main, optionmenu_language, "optionmenu_language"); + GLADE_HOOKUP_OBJECT (win_main, optionmenu_language2, "optionmenu_language2"); + GLADE_HOOKUP_OBJECT (win_main, optionmenu_bitrate, "optionmenu_bitrate"); + GLADE_HOOKUP_OBJECT (win_main, menu1, "menu1"); + GLADE_HOOKUP_OBJECT (win_main, _2, "_2"); + GLADE_HOOKUP_OBJECT (win_main, _4, "_4"); + GLADE_HOOKUP_OBJECT (win_main, _7, "_7"); + GLADE_HOOKUP_OBJECT (win_main, _10, "_10"); + GLADE_HOOKUP_OBJECT (win_main, _11, "_11"); + GLADE_HOOKUP_OBJECT (win_main, _12, "_12"); + GLADE_HOOKUP_OBJECT (win_main, _13, "_13"); + GLADE_HOOKUP_OBJECT (win_main, label8, "label8"); + GLADE_HOOKUP_OBJECT (win_main, frame_output, "frame_output"); + GLADE_HOOKUP_OBJECT (win_main, vbox2, "vbox2"); + GLADE_HOOKUP_OBJECT (win_main, hbox20, "hbox20"); + GLADE_HOOKUP_OBJECT (win_main, alignment11, "alignment11"); + GLADE_HOOKUP_OBJECT (win_main, label17, "label17"); + GLADE_HOOKUP_OBJECT (win_main, alignment12, "alignment12"); + GLADE_HOOKUP_OBJECT (win_main, optionmenu_format, "optionmenu_format"); + GLADE_HOOKUP_OBJECT (win_main, menu2, "menu2"); + GLADE_HOOKUP_OBJECT (win_main, auto1, "auto1"); + GLADE_HOOKUP_OBJECT (win_main, avi1, "avi1"); + GLADE_HOOKUP_OBJECT (win_main, mp1, "mp1"); + GLADE_HOOKUP_OBJECT (win_main, ogm1, "ogm1"); + GLADE_HOOKUP_OBJECT (win_main, hbox6, "hbox6"); + GLADE_HOOKUP_OBJECT (win_main, label18, "label18"); + GLADE_HOOKUP_OBJECT (win_main, combo2, "combo2"); + GLADE_HOOKUP_OBJECT (win_main, entry_file, "entry_file"); + GLADE_HOOKUP_OBJECT (win_main, button_browse_file, "button_browse_file"); + GLADE_HOOKUP_OBJECT (win_main, alignment2, "alignment2"); + GLADE_HOOKUP_OBJECT (win_main, hbox7, "hbox7"); + GLADE_HOOKUP_OBJECT (win_main, image4, "image4"); + GLADE_HOOKUP_OBJECT (win_main, label19, "label19"); + GLADE_HOOKUP_OBJECT (win_main, label9, "label9"); + GLADE_HOOKUP_OBJECT (win_main, hbuttonbox1, "hbuttonbox1"); + GLADE_HOOKUP_OBJECT (win_main, button_start, "button_start"); + GLADE_HOOKUP_OBJECT (win_main, alignment3, "alignment3"); + GLADE_HOOKUP_OBJECT (win_main, hbox9, "hbox9"); + GLADE_HOOKUP_OBJECT (win_main, button_start_image, "button_start_image"); + GLADE_HOOKUP_OBJECT (win_main, button_start_label, "button_start_label"); + GLADE_HOOKUP_OBJECT (win_main, hbox10, "hbox10"); + GLADE_HOOKUP_OBJECT (win_main, progressbar, "progressbar"); + GLADE_HOOKUP_OBJECT (win_main, statusbar, "statusbar"); + + return win_main; +} + +GtkWidget* +create_win_open (void) +{ + GtkWidget *win_open; + GtkWidget *ok_button1; + GtkWidget *cancel_button1; + + win_open = gtk_file_selection_new ("Select File"); + gtk_container_set_border_width (GTK_CONTAINER (win_open), 10); + gtk_window_set_modal (GTK_WINDOW (win_open), TRUE); + + ok_button1 = GTK_FILE_SELECTION (win_open)->ok_button; + gtk_widget_show (ok_button1); + GTK_WIDGET_SET_FLAGS (ok_button1, GTK_CAN_DEFAULT); + + cancel_button1 = GTK_FILE_SELECTION (win_open)->cancel_button; + gtk_widget_show (cancel_button1); + GTK_WIDGET_SET_FLAGS (cancel_button1, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) win_open, "delete_event", + G_CALLBACK (on_win_open_delete_event), + NULL); + g_signal_connect ((gpointer) ok_button1, "clicked", + G_CALLBACK (on_ok_button1_clicked), + NULL); + g_signal_connect ((gpointer) cancel_button1, "clicked", + G_CALLBACK (on_cancel_button1_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (win_open, win_open, "win_open"); + GLADE_HOOKUP_OBJECT_NO_REF (win_open, ok_button1, "ok_button1"); + GLADE_HOOKUP_OBJECT_NO_REF (win_open, cancel_button1, "cancel_button1"); + + return win_open; +} + +GtkWidget* +create_win_settings (void) +{ + GtkWidget *win_settings; + GtkWidget *vbox4; + GtkWidget *drawingarea; + GtkWidget *table5; + GtkWidget *vbox5; + GtkWidget *hbuttonbox2; + GtkWidget *button_settings_previous; + GtkWidget *alignment5; + GtkWidget *hbox12; + GtkWidget *image7; + GtkWidget *label22; + GtkWidget *button_settings_next; + GtkWidget *alignment6; + GtkWidget *hbox13; + GtkWidget *image8; + GtkWidget *label23; + GtkWidget *vbox6; + GtkWidget *hbox17; + GtkWidget *table8; + GtkObject *spinbutton_width_adj; + GtkWidget *spinbutton_width; + GtkObject *spinbutton_crop_top_adj; + GtkWidget *spinbutton_crop_top; + GtkWidget *label26; + GtkWidget *label25; + GtkWidget *label24; + GtkObject *spinbutton_crop_bottom_adj; + GtkWidget *spinbutton_crop_bottom; + GtkWidget *table9; + GtkObject *spinbutton_crop_left_adj; + GtkWidget *spinbutton_crop_left; + GtkWidget *label28; + GtkWidget *label27; + GtkObject *spinbutton_crop_right_adj; + GtkWidget *spinbutton_crop_right; + GtkWidget *checkbutton_deinterlace; + GtkWidget *hseparator1; + GtkWidget *table4; + GtkWidget *button1; + GtkWidget *alignment4; + GtkWidget *hbox11; + GtkWidget *image5; + GtkWidget *label20; + GtkWidget *label_settings; + + win_settings = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (win_settings), "Picture settings"); + gtk_window_set_modal (GTK_WINDOW (win_settings), TRUE); + + vbox4 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox4); + gtk_container_add (GTK_CONTAINER (win_settings), vbox4); + + drawingarea = gtk_drawing_area_new (); + gtk_widget_show (drawingarea); + gtk_box_pack_start (GTK_BOX (vbox4), drawingarea, TRUE, TRUE, 10); + + table5 = gtk_table_new (1, 3, FALSE); + gtk_widget_show (table5); + gtk_box_pack_start (GTK_BOX (vbox4), table5, TRUE, TRUE, 0); + + vbox5 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox5); + gtk_table_attach (GTK_TABLE (table5), vbox5, 2, 3, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox2); + gtk_box_pack_start (GTK_BOX (vbox5), hbuttonbox2, TRUE, TRUE, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_END); + + button_settings_previous = gtk_button_new (); + gtk_widget_show (button_settings_previous); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button_settings_previous); + gtk_widget_set_sensitive (button_settings_previous, FALSE); + GTK_WIDGET_SET_FLAGS (button_settings_previous, GTK_CAN_DEFAULT); + + alignment5 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment5); + gtk_container_add (GTK_CONTAINER (button_settings_previous), alignment5); + + hbox12 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox12); + gtk_container_add (GTK_CONTAINER (alignment5), hbox12); + + image7 = gtk_image_new_from_stock ("gtk-go-back", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image7); + gtk_box_pack_start (GTK_BOX (hbox12), image7, FALSE, FALSE, 0); + + label22 = gtk_label_new_with_mnemonic ("Previous"); + gtk_widget_show (label22); + gtk_box_pack_start (GTK_BOX (hbox12), label22, FALSE, FALSE, 0); + + button_settings_next = gtk_button_new (); + gtk_widget_show (button_settings_next); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), button_settings_next); + GTK_WIDGET_SET_FLAGS (button_settings_next, GTK_CAN_DEFAULT); + + alignment6 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment6); + gtk_container_add (GTK_CONTAINER (button_settings_next), alignment6); + + hbox13 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox13); + gtk_container_add (GTK_CONTAINER (alignment6), hbox13); + + image8 = gtk_image_new_from_stock ("gtk-go-forward", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image8); + gtk_box_pack_start (GTK_BOX (hbox13), image8, FALSE, FALSE, 0); + + label23 = gtk_label_new_with_mnemonic ("Next"); + gtk_widget_show (label23); + gtk_box_pack_start (GTK_BOX (hbox13), label23, FALSE, FALSE, 0); + + vbox6 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox6); + gtk_table_attach (GTK_TABLE (table5), vbox6, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (GTK_FILL), 0, 0); + + hbox17 = gtk_hbox_new (TRUE, 0); + gtk_widget_show (hbox17); + gtk_box_pack_start (GTK_BOX (vbox6), hbox17, TRUE, TRUE, 0); + + table8 = gtk_table_new (3, 3, FALSE); + gtk_widget_show (table8); + gtk_box_pack_start (GTK_BOX (hbox17), table8, TRUE, TRUE, 5); + + spinbutton_width_adj = gtk_adjustment_new (0, 0, 4096, 16, 16, 10); + spinbutton_width = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_width_adj), 1, 0); + gtk_widget_show (spinbutton_width); + gtk_table_attach (GTK_TABLE (table8), spinbutton_width, 2, 3, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton_width), TRUE); + + spinbutton_crop_top_adj = gtk_adjustment_new (0, 0, 4096, 2, 10, 10); + spinbutton_crop_top = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_crop_top_adj), 1, 0); + gtk_widget_show (spinbutton_crop_top); + gtk_table_attach (GTK_TABLE (table8), spinbutton_crop_top, 2, 3, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + label26 = gtk_label_new ("Bottom crop"); + gtk_widget_show (label26); + gtk_table_attach (GTK_TABLE (table8), label26, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label26), 0, 0.5); + + label25 = gtk_label_new ("Top crop"); + gtk_widget_show (label25); + gtk_table_attach (GTK_TABLE (table8), label25, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label25), 0, 0.5); + + label24 = gtk_label_new ("Picture width"); + gtk_widget_show (label24); + gtk_table_attach (GTK_TABLE (table8), label24, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + spinbutton_crop_bottom_adj = gtk_adjustment_new (0, 0, 4096, 2, 10, 10); + spinbutton_crop_bottom = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_crop_bottom_adj), 1, 0); + gtk_widget_show (spinbutton_crop_bottom); + gtk_table_attach (GTK_TABLE (table8), spinbutton_crop_bottom, 2, 3, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + table9 = gtk_table_new (3, 3, FALSE); + gtk_widget_show (table9); + gtk_box_pack_start (GTK_BOX (hbox17), table9, TRUE, TRUE, 5); + + spinbutton_crop_left_adj = gtk_adjustment_new (0, 0, 4096, 2, 10, 10); + spinbutton_crop_left = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_crop_left_adj), 1, 0); + gtk_widget_show (spinbutton_crop_left); + gtk_table_attach (GTK_TABLE (table9), spinbutton_crop_left, 2, 3, 1, 2, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + label28 = gtk_label_new ("Right crop"); + gtk_widget_show (label28); + gtk_table_attach (GTK_TABLE (table9), label28, 0, 1, 2, 3, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label28), 0, 0.5); + + label27 = gtk_label_new ("Left crop"); + gtk_widget_show (label27); + gtk_table_attach (GTK_TABLE (table9), label27, 0, 1, 1, 2, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label27), 0, 0.5); + + spinbutton_crop_right_adj = gtk_adjustment_new (0, 0, 4096, 2, 10, 10); + spinbutton_crop_right = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_crop_right_adj), 1, 0); + gtk_widget_show (spinbutton_crop_right); + gtk_table_attach (GTK_TABLE (table9), spinbutton_crop_right, 2, 3, 2, 3, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + checkbutton_deinterlace = gtk_check_button_new_with_mnemonic ("deinterlace"); + gtk_widget_show (checkbutton_deinterlace); + gtk_table_attach (GTK_TABLE (table9), checkbutton_deinterlace, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + hseparator1 = gtk_hseparator_new (); + gtk_widget_show (hseparator1); + gtk_box_pack_start (GTK_BOX (vbox4), hseparator1, FALSE, TRUE, 0); + + table4 = gtk_table_new (1, 2, FALSE); + gtk_widget_show (table4); + gtk_box_pack_start (GTK_BOX (vbox4), table4, FALSE, TRUE, 5); + + button1 = gtk_button_new (); + gtk_widget_show (button1); + gtk_table_attach (GTK_TABLE (table4), button1, 1, 2, 0, 1, + (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + alignment4 = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_widget_show (alignment4); + gtk_container_add (GTK_CONTAINER (button1), alignment4); + + hbox11 = gtk_hbox_new (FALSE, 2); + gtk_widget_show (hbox11); + gtk_container_add (GTK_CONTAINER (alignment4), hbox11); + + image5 = gtk_image_new_from_stock ("gtk-apply", GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image5); + gtk_box_pack_start (GTK_BOX (hbox11), image5, FALSE, FALSE, 0); + + label20 = gtk_label_new_with_mnemonic ("Ok"); + gtk_widget_show (label20); + gtk_box_pack_start (GTK_BOX (hbox11), label20, FALSE, FALSE, 0); + + label_settings = gtk_label_new ("label21"); + gtk_widget_show (label_settings); + gtk_table_attach (GTK_TABLE (table4), label_settings, 0, 1, 0, 1, + (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label_settings), 0, 0.5); + + g_signal_connect ((gpointer) win_settings, "delete_event", + G_CALLBACK (on_win_settings_delete_event), + NULL); + g_signal_connect ((gpointer) button_settings_previous, "clicked", + G_CALLBACK (on_button_settings_previous_clicked), + NULL); + g_signal_connect ((gpointer) button_settings_next, "clicked", + G_CALLBACK (on_button_settings_next_clicked), + NULL); + g_signal_connect ((gpointer) spinbutton_width, "value_changed", + G_CALLBACK (on_spinbutton_width_value_changed), + NULL); + g_signal_connect ((gpointer) spinbutton_crop_top, "value_changed", + G_CALLBACK (on_spinbutton_crop_top_value_changed), + NULL); + g_signal_connect ((gpointer) spinbutton_crop_bottom, "value_changed", + G_CALLBACK (on_spinbutton_crop_bottom_value_changed), + NULL); + g_signal_connect ((gpointer) spinbutton_crop_left, "value_changed", + G_CALLBACK (on_spinbutton_crop_left_value_changed), + NULL); + g_signal_connect ((gpointer) spinbutton_crop_right, "value_changed", + G_CALLBACK (on_spinbutton_crop_right_value_changed), + NULL); + g_signal_connect ((gpointer) checkbutton_deinterlace, "toggled", + G_CALLBACK (on_checkbutton_deinterlace_toggled), + NULL); + g_signal_connect ((gpointer) button1, "clicked", + G_CALLBACK (on_button_ok_settings_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (win_settings, win_settings, "win_settings"); + GLADE_HOOKUP_OBJECT (win_settings, vbox4, "vbox4"); + GLADE_HOOKUP_OBJECT (win_settings, drawingarea, "drawingarea"); + GLADE_HOOKUP_OBJECT (win_settings, table5, "table5"); + GLADE_HOOKUP_OBJECT (win_settings, vbox5, "vbox5"); + GLADE_HOOKUP_OBJECT (win_settings, hbuttonbox2, "hbuttonbox2"); + GLADE_HOOKUP_OBJECT (win_settings, button_settings_previous, "button_settings_previous"); + GLADE_HOOKUP_OBJECT (win_settings, alignment5, "alignment5"); + GLADE_HOOKUP_OBJECT (win_settings, hbox12, "hbox12"); + GLADE_HOOKUP_OBJECT (win_settings, image7, "image7"); + GLADE_HOOKUP_OBJECT (win_settings, label22, "label22"); + GLADE_HOOKUP_OBJECT (win_settings, button_settings_next, "button_settings_next"); + GLADE_HOOKUP_OBJECT (win_settings, alignment6, "alignment6"); + GLADE_HOOKUP_OBJECT (win_settings, hbox13, "hbox13"); + GLADE_HOOKUP_OBJECT (win_settings, image8, "image8"); + GLADE_HOOKUP_OBJECT (win_settings, label23, "label23"); + GLADE_HOOKUP_OBJECT (win_settings, vbox6, "vbox6"); + GLADE_HOOKUP_OBJECT (win_settings, hbox17, "hbox17"); + GLADE_HOOKUP_OBJECT (win_settings, table8, "table8"); + GLADE_HOOKUP_OBJECT (win_settings, spinbutton_width, "spinbutton_width"); + GLADE_HOOKUP_OBJECT (win_settings, spinbutton_crop_top, "spinbutton_crop_top"); + GLADE_HOOKUP_OBJECT (win_settings, label26, "label26"); + GLADE_HOOKUP_OBJECT (win_settings, label25, "label25"); + GLADE_HOOKUP_OBJECT (win_settings, label24, "label24"); + GLADE_HOOKUP_OBJECT (win_settings, spinbutton_crop_bottom, "spinbutton_crop_bottom"); + GLADE_HOOKUP_OBJECT (win_settings, table9, "table9"); + GLADE_HOOKUP_OBJECT (win_settings, spinbutton_crop_left, "spinbutton_crop_left"); + GLADE_HOOKUP_OBJECT (win_settings, label28, "label28"); + GLADE_HOOKUP_OBJECT (win_settings, label27, "label27"); + GLADE_HOOKUP_OBJECT (win_settings, spinbutton_crop_right, "spinbutton_crop_right"); + GLADE_HOOKUP_OBJECT (win_settings, checkbutton_deinterlace, "checkbutton_deinterlace"); + GLADE_HOOKUP_OBJECT (win_settings, hseparator1, "hseparator1"); + GLADE_HOOKUP_OBJECT (win_settings, table4, "table4"); + GLADE_HOOKUP_OBJECT (win_settings, button1, "button1"); + GLADE_HOOKUP_OBJECT (win_settings, alignment4, "alignment4"); + GLADE_HOOKUP_OBJECT (win_settings, hbox11, "hbox11"); + GLADE_HOOKUP_OBJECT (win_settings, image5, "image5"); + GLADE_HOOKUP_OBJECT (win_settings, label20, "label20"); + GLADE_HOOKUP_OBJECT (win_settings, label_settings, "label_settings"); + + return win_settings; +} + diff --git a/gtk2/interface.h b/gtk2/interface.h new file mode 100644 index 000000000..303e644b8 --- /dev/null +++ b/gtk2/interface.h @@ -0,0 +1,7 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_win_main (void); +GtkWidget* create_win_open (void); +GtkWidget* create_win_settings (void); diff --git a/gtk2/main.c b/gtk2/main.c new file mode 100644 index 000000000..f0d5b406e --- /dev/null +++ b/gtk2/main.c @@ -0,0 +1,409 @@ +/* + * Initial main.c file generated by Glade. Edit as required. + * Glade will not overwrite this file. + */ + +#include "../core/HandBrake.h" + +#include <gtk/gtk.h> + +#include "interface.h" +#include "support.h" + +#include "status.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +GtkWidget *hb_win_main = NULL; +HBHandle *hb_handle = NULL; +HBStatus *hb_status = NULL; + +static int HBMain( void *data ); + +/* libhb callbacks */ +static void Scanning( void * data, int title, int titleCount ); +static void ScanDone( void * data, HBList * titleList ); +static void Encoding( void * data, float position, int pass, + int passCount, float frameRate, + float avgFrameRate, int remainingTime ); +static void RipDone( void * data, int result ); + + +int main (int argc, char **argv ) +{ + HBCallbacks callbacks; + GtkWidget *widget; + GList *items = NULL; + + int i_dummy; + + /* Create HB stuff */ + if( ( hb_handle = HBInit( 1, 0 ) ) == NULL ) + { + g_print( "HBInit: failed\n" ); + return -1; + } + + /* Emulate a HBStatus */ + hb_status = malloc( sizeof( HBStatus ) ); + hb_status->i_state = HB_STATE_NEED_DEVICE; + hb_status->b_new = 1; + hb_status->i_title = 0; + hb_status->i_title_count = 0; + hb_status->titleList = NULL; + hb_status->position = 0.0; + hb_status->i_remaining = 0; + hb_status->fps = 0.0; + + /* Set libhb callbacks */ + callbacks.data = NULL; + callbacks.scanning = Scanning; + callbacks.scanDone = ScanDone; + callbacks.encoding = Encoding; + callbacks.ripDone = RipDone; + HBSetCallbacks( hb_handle, callbacks ); + + gtk_set_locale (); + gtk_init (&argc, &argv); + + //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + + /* Create the main window */ + hb_win_main = create_win_main(); + gtk_window_set_title( GTK_WINDOW(hb_win_main), "HandBrake " HB_VERSION ); + + widget = lookup_widget( hb_win_main, "combo1" ); + gtk_combo_disable_activate( GTK_COMBO( widget ) ); + + widget = lookup_widget( hb_win_main, "combo2" ); + gtk_combo_disable_activate( GTK_COMBO( widget ) ); + + widget = lookup_widget( hb_win_main, "optionmenu_bitrate" ); + gtk_option_menu_set_history( GTK_OPTION_MENU(widget), 2 ); + + /* build dvd list */ + items = g_list_append (items, "" ); + items = g_list_append (items, "/dev/dvd" ); + gtk_combo_set_popdown_strings( GTK_COMBO(lookup_widget( hb_win_main, "combo1") ), items ); + + /* Display the main window */ + gtk_widget_show( hb_win_main ); + + i_dummy = gtk_timeout_add( 100, (GtkFunction)HBMain, NULL ); + gtk_main(); + gtk_timeout_remove( i_dummy ); + + return 0; +} + +static void StatusBarUpdate( char *msg ) +{ + GtkWidget *widget = lookup_widget( hb_win_main, "statusbar" ); + + gtk_statusbar_push( GTK_STATUSBAR(widget), + gtk_statusbar_get_context_id(GTK_STATUSBAR(widget), "status" ), + msg ); +} + +static void DisplayError( char *title, char *msg ) +{ + GtkWidget *dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, + "<b>%s</b>\n\n%s", title, msg ); + gtk_label_set_use_markup( GTK_LABEL( GTK_MESSAGE_DIALOG(dialog)->label), TRUE ); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK ); + gtk_window_set_modal( GTK_WINDOW(dialog), TRUE ); + gtk_dialog_run( GTK_DIALOG(dialog) ); + gtk_widget_destroy( dialog ); +} + +static void DisplayInfo( char *msg ) +{ + GtkWidget *dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO, GTK_BUTTONS_OK, msg ); + gtk_label_set_use_markup( GTK_LABEL( GTK_MESSAGE_DIALOG(dialog)->label), TRUE ); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK ); + gtk_window_set_modal( GTK_WINDOW(dialog), TRUE ); + gtk_dialog_run( GTK_DIALOG(dialog) ); + gtk_widget_destroy( dialog ); +} + +static int HBMain( void *data ) +{ + int b_new = hb_status->b_new; + GtkWidget *widget; + gchar msg[1000]; + + hb_status->b_new = 0; + + switch( hb_status->i_state ) + { + case HB_STATE_NEED_DEVICE: + if( b_new ) + { + g_print( "HBMain: HB_MODE_NEED_DEVICE\n" ); + gtk_widget_set_sensitive( lookup_widget( hb_win_main, "frame_dvd"), TRUE ); + StatusBarUpdate( "Enter a device" ); + } + break; + + case HB_STATE_SCANNING: + if( b_new ) + { + g_print( "HBMain: HB_MODE_SCANNING\n" ); + } + + gtk_widget_set_sensitive( lookup_widget( hb_win_main, "frame_dvd"), FALSE ); + + gtk_progress_bar_pulse( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" ) )); + if( hb_status->i_title ) + { + sprintf( msg, "Scanning title %d/%d...", hb_status->i_title, hb_status->i_title_count ); + } + else + { + sprintf( msg, "Opening device..." ); + } + StatusBarUpdate( msg ); + break; + + case HB_STATE_INVALID_DEVICE: + if( b_new ) + { + g_print( "HBMain: HB_MODE_INVALID_DEVICE\n" ); + + gtk_widget_set_sensitive( lookup_widget( hb_win_main, "frame_dvd"), TRUE ); + + gtk_entry_set_text( GTK_ENTRY(lookup_widget( hb_win_main, "entry_device")), "" ); + + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), 0.0 ); + + StatusBarUpdate( "Enter a valid device" ); + + /* error dialog */ + DisplayError( "Invalid device", "Please select a valide device" ); + } + break; + + case HB_STATE_READY_TO_RIP: + if( b_new ) + { + GtkWidget *optionmenu_title = lookup_widget( hb_win_main, "optionmenu_title" ); + GtkWidget *menu; + GtkWidget *item; + int i; + + g_print( "HBMain: HB_MODE_READY_TO_RIP\n" ); + + /* create title menu */ + menu = gtk_menu_new(); + for( i = 0; i < HBListCount( hb_status->titleList ); i++ ) + { + HBTitle *title = (HBTitle*) HBListItemAt( hb_status->titleList, i ); + char string[1024]; + + sprintf( string, "%d - %02dh%02dm%02ds", + title->index, title->length / 3600, + ( title->length % 3600 ) / 60, + title->length % 60 ); + + item = gtk_menu_item_new_with_mnemonic( string ); + gtk_widget_show( item ); + gtk_menu_shell_append( GTK_MENU_SHELL(menu), item ); + } + + gtk_option_menu_set_menu( GTK_OPTION_MENU(optionmenu_title), menu ); + GLADE_HOOKUP_OBJECT( hb_win_main, menu, "menu_title" ); + + /* unhide */ + widget = lookup_widget( hb_win_main, "vbox_parameters" ); + gtk_widget_show( widget ); + + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), 0.0 ); + gtk_progress_bar_set_text( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), "" ); + + StatusBarUpdate( "Select your parameters" ); + } + break; + + case HB_STATE_ENCODING: + if( b_new ) + { + /* change the name to Stop */ + widget = lookup_widget( hb_win_main, "button_start_label" ); + gtk_label_set_text( GTK_LABEL( widget ), "Stop" ); + + widget = lookup_widget( hb_win_main, "button_start_image" ); + gtk_image_set_from_stock( GTK_IMAGE(widget), "gtk-cancel", GTK_ICON_SIZE_BUTTON ); + + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_video"), FALSE ); + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_audio"), FALSE ); + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_output"), FALSE ); + } + + if( hb_status->position <= 0 ) + { + StatusBarUpdate( "Starting..." ); + } + else + { + char string[1024]; + + /* Status bar */ + sprintf( string, "Encoding: %02dh%02dm%02ds remaining", + hb_status->i_remaining / 3600, + ( hb_status->i_remaining % 3600 ) / 60, + hb_status->i_remaining % 60 ); + StatusBarUpdate( string ); + + /* Progressbar */ + sprintf( string, "%.2f %% (%.2f fps)", 100 * hb_status->position, hb_status->fps ); + gtk_progress_bar_set_text( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), string ); + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), hb_status->position ); + } + break; + + case HB_STATE_DONE: + case HB_STATE_CANCELED: + if( b_new ) + { + g_print( "HBMain: HB_MODE_DONE/HB_MODE_CANCELED\n" ); + + /* change the name to Start */ + widget = lookup_widget( hb_win_main, "button_start_label" ); + gtk_label_set_text( GTK_LABEL( widget ), "Start" ); + + widget = lookup_widget( hb_win_main, "button_start_image" ); + gtk_image_set_from_stock( GTK_IMAGE(widget), "gtk-apply", GTK_ICON_SIZE_BUTTON ); + + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), 0.0 ); + gtk_progress_bar_set_text( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), "" ); + + if( hb_status->i_state == HB_STATE_DONE ) + { + StatusBarUpdate( "Done." ); + DisplayInfo( "Encoding finished with success." ); + } + else + { + StatusBarUpdate( "Canceled." ); + DisplayInfo("Encoding canceled."); + } + + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_video"), TRUE ); + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_audio"), TRUE ); + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_output"), TRUE ); + } + break; + + case HB_STATE_ERROR: + if( b_new ) + { + char *msg = "Unknown"; + + g_print( "HBMain: HB_MODE_ERROR\n" ); + + /* change the name to Start */ + widget = lookup_widget( hb_win_main, "button_start_label" ); + gtk_label_set_text( GTK_LABEL( widget ), "Start" ); + + widget = lookup_widget( hb_win_main, "button_start_image" ); + gtk_image_set_from_stock( GTK_IMAGE(widget), "gtk-apply", GTK_ICON_SIZE_BUTTON ); + + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), 0.0 ); + gtk_progress_bar_set_text( GTK_PROGRESS_BAR(lookup_widget( hb_win_main, "progressbar" )), "" ); + + StatusBarUpdate( "Error." ); + switch( hb_status->i_error ) + { +#if 0 + case HB_ERROR_A52_SYNC: + msg = "corrupted AC3 data."; + break; + case HB_ERROR_AVI_WRITE: + msg = "could not write to file."; + break; + case HB_ERROR_DVD_OPEN: + msg = "could not open device."; + break; + case HB_ERROR_DVD_READ: + msg = "DVD read failed."; + break; + case HB_ERROR_MP3_INIT: + msg = "could not init MP3 encoder."; + break; + case HB_ERROR_MP3_ENCODE: + msg = "MP3 encoder failed."; + break; + case HB_ERROR_MPEG4_INIT: + msg = "could not init MPEG4 encoder."; + break; +#endif + default: + msg = "Generic error"; + break; + } + DisplayError( "An error occured", msg ); + + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_video"), TRUE ); + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_audio"), TRUE ); + gtk_widget_set_sensitive( lookup_widget(hb_win_main, "frame_output"), TRUE ); + } + break; + } + + + return TRUE; +} + + +static void Scanning( void * data, int title, int titleCount ) +{ + if( hb_status->i_state != HB_STATE_SCANNING ) + { + hb_status->i_state = HB_STATE_SCANNING; + hb_status->b_new = 1; + } + hb_status->i_title = title; + hb_status->i_title_count = titleCount; +} + +static void ScanDone( void * data, HBList * titleList ) +{ + if( titleList == NULL ) + { + hb_status->i_state = HB_STATE_INVALID_DEVICE; + } + else + { + hb_status->i_state = HB_STATE_READY_TO_RIP; + } + hb_status->b_new = 1; + + hb_status->titleList = titleList; +} + +static void Encoding( void * data, float position, int pass, + int passCount, float frameRate, + float avgFrameRate, int remainingTime ) +{ + if( hb_status->i_state != HB_STATE_ENCODING ) + { + hb_status->i_state = HB_STATE_ENCODING; + hb_status->b_new = 1; + } + + hb_status->position = position; + hb_status->fps = frameRate; + hb_status->i_remaining = remainingTime; +} + +static void RipDone( void * data, int result ) +{ + /* TODO check result */ + hb_status->i_state = HB_STATE_DONE; + hb_status->b_new = 1; +} + diff --git a/gtk2/status.h b/gtk2/status.h new file mode 100644 index 000000000..c98e4c9b0 --- /dev/null +++ b/gtk2/status.h @@ -0,0 +1,33 @@ +/* + * + */ + +enum HBState_e +{ + HB_STATE_NEED_DEVICE, + HB_STATE_SCANNING, + HB_STATE_INVALID_DEVICE, + HB_STATE_READY_TO_RIP, + HB_STATE_ENCODING, + HB_STATE_DONE, + HB_STATE_CANCELED, + HB_STATE_ERROR, +}; + +typedef struct +{ + int i_state; + int i_error; + int b_new; + + int i_title; + int i_title_count; + + HBList *titleList; + + float position; + int i_remaining; + float fps; + +} HBStatus; + diff --git a/gtk2/support.c b/gtk2/support.c new file mode 100644 index 000000000..7dc3c78cb --- /dev/null +++ b/gtk2/support.c @@ -0,0 +1,144 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <gtk/gtk.h> + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +static GList *pixmaps_directories = NULL; + +/* Use this function to set the directory containing installed pixmaps. */ +void +add_pixmap_directory (const gchar *directory) +{ + pixmaps_directories = g_list_prepend (pixmaps_directories, + g_strdup (directory)); +} + +/* This is an internally used function to find pixmap files. */ +static gchar* +find_pixmap_file (const gchar *filename) +{ + GList *elem; + + /* We step through each of the pixmaps directory to find it. */ + elem = pixmaps_directories; + while (elem) + { + gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, + G_DIR_SEPARATOR_S, filename); + if (g_file_test (pathname, G_FILE_TEST_EXISTS)) + return pathname; + g_free (pathname); + elem = elem->next; + } + return NULL; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + gchar *pathname = NULL; + GtkWidget *pixmap; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = find_pixmap_file (filename); + + if (!pathname) + { + g_warning ("Couldn't find pixmap file: %s", filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + diff --git a/gtk2/support.h b/gtk2/support.h new file mode 100644 index 000000000..2dea079c2 --- /dev/null +++ b/gtk2/support.h @@ -0,0 +1,44 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtk/gtk.h> + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + +/* Use this function to set the directory containing installed pixmaps. */ +void add_pixmap_directory (const gchar *directory); + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +void glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description); + diff --git a/macosx/Controller.h b/macosx/Controller.h index 435e2216e..400246af8 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -1,4 +1,4 @@ -/* $Id: Controller.h,v 1.6 2003/11/13 01:40:44 titer Exp $ +/* $Id: Controller.h,v 1.14 2004/02/13 13:45:51 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -13,51 +13,65 @@ @interface HBController : NSObject { - bool fDie; - IBOutlet NSWindow * fWindow; /* Scan view */ - IBOutlet NSView * fScanView; - IBOutlet NSMatrix * fScanMatrix; - IBOutlet NSPopUpButton * fDVDPopUp; - IBOutlet NSTextField * fDVDFolderField; - IBOutlet NSButton * fScanBrowseButton; - IBOutlet NSTextField * fScanStatusField; - IBOutlet NSProgressIndicator * fScanProgress; - IBOutlet NSButton * fScanButton; + IBOutlet NSView * fScView; + IBOutlet NSTextField * fScWelcomeField; + IBOutlet NSTextField * fScSelectField; + IBOutlet NSMatrix * fScMatrix; + IBOutlet NSButtonCell * fScDetectedCell; + IBOutlet NSPopUpButton * fScDetectedPopUp; + IBOutlet NSButtonCell * fScFolderCell; + IBOutlet NSTextField * fScFolderField; + IBOutlet NSButton * fScBrowseButton; + IBOutlet NSTextField * fScStatusField; + IBOutlet NSProgressIndicator * fScProgress; + IBOutlet NSButton * fScOpenButton; IBOutlet NSView * fTempView; /* Rip view */ IBOutlet NSView * fRipView; + /* General box */ + IBOutlet NSTextField * fRipGeneralField; + IBOutlet NSTextField * fRipTitleField; + IBOutlet NSPopUpButton * fRipTitlePopUp; + IBOutlet NSTextField * fRipFormatField; + IBOutlet NSPopUpButton * fRipFormatPopUp; + IBOutlet NSTextField * fRipFileField1; + IBOutlet NSTextField * fRipFileField2; + IBOutlet NSButton * fRipBrowseButton; + /* Video box */ - IBOutlet NSPopUpButton * fTitlePopUp; - IBOutlet NSPopUpButton * fVideoCodecPopUp; - IBOutlet NSMatrix * fVideoMatrix; - IBOutlet NSTextField * fCustomBitrateField; - IBOutlet HBTargetSizeField * fTargetSizeField; - IBOutlet NSButton * fTwoPassCheck; - IBOutlet NSButton * fCropButton; + IBOutlet NSTextField * fRipVideoField; + IBOutlet NSTextField * fRipEncoderField; + IBOutlet NSPopUpButton * fRipEncoderPopUp; + IBOutlet NSTextField * fRipBitrateField; + IBOutlet NSMatrix * fRipVideoMatrix; + IBOutlet NSButtonCell * fRipCustomCell; + IBOutlet NSTextField * fRipCustomField; + IBOutlet NSButtonCell * fRipTargetCell; + IBOutlet HBTargetSizeField * fRipTargetField; + IBOutlet NSButton * fRipTwoPassCheck; + IBOutlet NSButton * fRipCropButton; /* Audio box */ - IBOutlet NSPopUpButton * fLanguagePopUp; - IBOutlet NSPopUpButton * fSecondaryLanguagePopUp; - IBOutlet NSPopUpButton * fAudioCodecPopUp; - IBOutlet NSPopUpButton * fAudioBitratePopUp; - - /* Destination box */ - IBOutlet NSPopUpButton * fFileFormatPopUp; - IBOutlet NSTextField * fFileField; - IBOutlet NSButton * fFileBrowseButton; + IBOutlet NSTextField * fRipAudioField; + IBOutlet NSTextField * fRipLang1Field; + IBOutlet NSPopUpButton * fRipLang1PopUp; + IBOutlet NSTextField * fRipLang2Field; + IBOutlet NSPopUpButton * fRipLang2PopUp; + IBOutlet NSTextField * fRipAudBitField; + IBOutlet NSPopUpButton * fRipAudBitPopUp; /* Bottom */ IBOutlet NSTextField * fRipStatusField; IBOutlet NSTextField * fRipInfoField; IBOutlet NSProgressIndicator * fRipProgress; - IBOutlet NSButton * fPauseButton; - IBOutlet NSButton * fRipButton; + IBOutlet NSButton * fRipPauseButton; + IBOutlet NSButton * fRipRipButton; /* "Done" alert panel */ IBOutlet NSPanel * fDonePanel; @@ -65,25 +79,41 @@ /* Crop & scale panel */ IBOutlet NSPanel * fPicturePanel; IBOutlet HBPictureGLView * fPictureGLView; - IBOutlet NSTextField * fWidthField; + IBOutlet NSTextField * fWidthField1; + IBOutlet NSTextField * fWidthField2; IBOutlet NSStepper * fWidthStepper; IBOutlet NSButton * fDeinterlaceCheck; - IBOutlet NSTextField * fTopField; + IBOutlet NSTextField * fTopField1; + IBOutlet NSTextField * fTopField2; IBOutlet NSStepper * fTopStepper; - IBOutlet NSTextField * fBottomField; + IBOutlet NSTextField * fBottomField1; + IBOutlet NSTextField * fBottomField2; IBOutlet NSStepper * fBottomStepper; - IBOutlet NSTextField * fLeftField; + IBOutlet NSTextField * fLeftField1; + IBOutlet NSTextField * fLeftField2; IBOutlet NSStepper * fLeftStepper; - IBOutlet NSTextField * fRightField; + IBOutlet NSTextField * fRightField1; + IBOutlet NSTextField * fRightField2; IBOutlet NSStepper * fRightStepper; - IBOutlet NSTextField * fInfoField; - IBOutlet NSButton * fOpenGLCheck; IBOutlet NSButton * fPreviousButton; IBOutlet NSButton * fNextButton; + IBOutlet NSButton * fAutocropButton; + IBOutlet NSButton * fOpenGLCheck; + IBOutlet NSTextField * fInfoField; + IBOutlet NSButton * fCloseButton; int fPicture; HBHandle * fHandle; + int fTitle; + int fTitleCount; HBList * fTitleList; + float fPosition; + int fPass; + int fPassCount; + float fCurFrameRate; + float fAvgFrameRate; + int fRemainingTime; + int fResult; } - (IBAction) ScanMatrixChanged: (id) sender; @@ -93,6 +123,7 @@ - (IBAction) Scan: (id) sender; - (IBAction) TitlePopUpChanged: (id) sender; +- (IBAction) FormatPopUpChanged: (id) sender; - (IBAction) VideoMatrixChanged: (id) sender; - (IBAction) AudioPopUpChanged: (id) sender; - (IBAction) BrowseFile: (id) sender; @@ -113,8 +144,15 @@ - (IBAction) PreviousPicture: (id) sender; - (IBAction) NextPicture: (id) sender; - (IBAction) UpdatePicture: (id) sender; +- (IBAction) AutoCrop: (id) sender; -- (void) UpdateIntf: (NSTimer *) timer; - (void) DetectDrives: (NSNotification *) notification; +/* libhb callbacks */ +- (void) Scanning: (id) sender; +- (void) ScanDone: (id) sender; +- (void) Encoding: (id) sender; +- (void) RipDone: (id) sender; + @end + diff --git a/macosx/Controller.mm b/macosx/Controller.mm index ea5a2c161..206c76369 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -1,4 +1,4 @@ -/* $Id: Controller.mm,v 1.10 2003/11/13 01:40:44 titer Exp $ +/* $Id: Controller.mm,v 1.27 2004/02/18 17:07:20 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -12,19 +12,34 @@ #include "Controller.h" +#define _(a) NSLocalizedString(a,nil) + +static void _Scanning( void * data, int title, int titleCount ); +static void _ScanDone( void * data, HBList * titleList ); +static void _Encoding( void * data, float position, int pass, + int passCount, float curFrameRate, + float avgFrameRate, int remainingTime ); +static void _RipDone( void * data, int result ); + +/******************************* + * HBController implementation * + *******************************/ @implementation HBController - (void) applicationDidFinishLaunching: (NSNotification *) notification { /* Init libhb */ + HBCallbacks callbacks; + callbacks.data = self; + callbacks.scanning = _Scanning; + callbacks.scanDone = _ScanDone; + callbacks.encoding = _Encoding; + callbacks.ripDone = _RipDone; + fHandle = HBInit( 1, 0 ); - [fPictureGLView SetHandle: fHandle]; + HBSetCallbacks( fHandle, callbacks ); - /* Update the GUI every 1/10 sec */ - fDie = false; - [NSTimer scheduledTimerWithTimeInterval: 0.1 - target: self selector: @selector( UpdateIntf: ) - userInfo: nil repeats: YES]; + [fPictureGLView SetHandle: fHandle]; /* Detect drives mounted after the app is started */ [[[NSWorkspace sharedWorkspace] notificationCenter] @@ -36,7 +51,6 @@ (NSApplication *) app { /* Clean up */ - fDie = true; HBClose( &fHandle ); return NSTerminateNow; @@ -44,33 +58,99 @@ - (void) awakeFromNib { - [fDVDPopUp removeAllItems]; - [fScanProgress setStyle: NSProgressIndicatorSpinningStyle]; - [fScanProgress setDisplayedWhenStopped: NO]; - [fVideoCodecPopUp removeAllItems]; - [fVideoCodecPopUp addItemWithTitle: @"MPEG-4 (Ffmpeg)"]; - [fVideoCodecPopUp addItemWithTitle: @"MPEG-4 (XviD)"]; - [fVideoCodecPopUp selectItemWithTitle: @"MPEG-4 (Ffmpeg)"]; - [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" ) ); - [fFileField setStringValue: [NSString stringWithCString: string]]; + /* Strings for the Scan view */ + [fScWelcomeField setStringValue: _( @"Welcome to HandBrake" )]; + [fScSelectField setStringValue: _( @"Select a DVD:" )]; + [fScDetectedCell setTitle: _( @"Detected volume" )]; + [fScDetectedPopUp removeAllItems]; + [fScFolderCell setTitle: _( @"DVD Folder" )]; + [fScBrowseButton setTitle: _( @"Browse" )]; + [fScStatusField setStringValue: @""]; + [fScOpenButton setTitle: _( @"Open" )]; + + /* Strings for the Rip view */ + /* General box */ + [fRipGeneralField setStringValue: _( @"General" )]; + [fRipTitleField setStringValue: _( @"DVD title" )]; + [fRipTitlePopUp removeAllItems]; + [fRipFormatField setStringValue: _( @"Output format" )]; + [fRipFormatPopUp removeAllItems]; + [fRipFormatPopUp addItemWithTitle: + _( @"MP4 file / MPEG-4 video / AAC audio" )]; + [fRipFormatPopUp addItemWithTitle: + _( @"AVI file / MPEG-4 video / MP3 audio" )]; + [fRipFormatPopUp addItemWithTitle: + _( @"AVI file / H264 video / MP3 audio" )]; + [fRipFormatPopUp addItemWithTitle: + _( @"OGM file / MPEG-4 video / Vorbis audio" )]; + [fRipFileField1 setStringValue: _( @"File" )]; + [fRipFileField2 setStringValue: [NSString stringWithFormat: + @"%@/Desktop/Movie.mp4", NSHomeDirectory()]]; + [fRipBrowseButton setTitle: _( @"Browse" )]; + + /* Video box */ + [fRipVideoField setStringValue: _( @"Video" )]; + [fRipEncoderField setStringValue: _( @"MPEG-4 encoder" )]; + [fRipEncoderPopUp removeAllItems]; + [fRipEncoderPopUp addItemWithTitle: @"FFmpeg"]; + [fRipEncoderPopUp addItemWithTitle: @"XviD"]; + [fRipBitrateField setStringValue: _( @"Bitrate" )]; + [fRipCustomCell setTitle: _( @"Custom (kbps)" )]; + [fRipCustomField setIntValue: 1024]; + [fRipTargetCell setTitle: _( @"Target size (MB)" )]; + [fRipTargetField setIntValue: 700]; + [fRipTwoPassCheck setTitle: _( @"2-pass encoding" )]; + [fRipCropButton setTitle: _( @"Crop & Scale..." )]; + + /* Audio box */ + [fRipAudioField setStringValue: _( @"Audio" )]; + [fRipLang1Field setStringValue: _( @"Language 1" )]; + [fRipLang1PopUp removeAllItems]; + [fRipLang2Field setStringValue: _( @"Language 2 (optional)" )]; + [fRipLang2PopUp removeAllItems]; + [fRipAudBitField setStringValue: _( @"Bitrate (kbps)" )]; + [fRipAudBitPopUp removeAllItems]; + [fRipAudBitPopUp addItemWithTitle: @"32"]; + [fRipAudBitPopUp addItemWithTitle: @"40"]; + [fRipAudBitPopUp addItemWithTitle: @"48"]; + [fRipAudBitPopUp addItemWithTitle: @"56"]; + [fRipAudBitPopUp addItemWithTitle: @"64"]; + [fRipAudBitPopUp addItemWithTitle: @"80"]; + [fRipAudBitPopUp addItemWithTitle: @"96"]; + [fRipAudBitPopUp addItemWithTitle: @"112"]; + [fRipAudBitPopUp addItemWithTitle: @"128"]; + [fRipAudBitPopUp addItemWithTitle: @"160"]; + [fRipAudBitPopUp addItemWithTitle: @"192"]; + [fRipAudBitPopUp addItemWithTitle: @"224"]; + [fRipAudBitPopUp addItemWithTitle: @"256"]; + [fRipAudBitPopUp addItemWithTitle: @"320"]; + [fRipAudBitPopUp selectItemWithTitle: @"128"]; + + /* Bottom */ + [fRipStatusField setStringValue: @""]; + [fRipInfoField setStringValue: @""]; + [fRipPauseButton setTitle: _( @"Pause" )]; + [fRipRipButton setTitle: _( @"Rip" )]; + + /* Strings for the crop panel */ + [fWidthField1 setStringValue: _( @"Picture width" )]; + [fDeinterlaceCheck setTitle: _( @"Deinterlace picture" )]; + [fTopField1 setStringValue: _( @"Top cropping" )]; + [fBottomField1 setStringValue: _( @"Bottom cropping" )]; + [fLeftField1 setStringValue: _( @"Left cropping" )]; + [fRightField1 setStringValue: _( @"Right cropping" )]; + [fPreviousButton setTitle: _( @"Previous" )]; + [fNextButton setTitle: _( @"Next" )]; + [fAutocropButton setTitle: _( @"Autocrop" )]; + [fOpenGLCheck setTitle: _( @"Useless OpenGL effects" )]; + [fInfoField setStringValue: @""]; + [fCloseButton setTitle: _( @"Close" )]; + + [self VideoMatrixChanged: self]; /* Show the scan view */ - [fWindow setContentSize: [fScanView frame].size]; - [fWindow setContentView: fScanView]; + [fWindow setContentSize: [fScView frame].size]; + [fWindow setContentView: fScView]; [fWindow center]; /* Detect DVD drives */ @@ -105,23 +185,30 @@ { if( returnCode == NSOKButton ) { - [fDVDFolderField setStringValue: + [fScFolderField setStringValue: [[sheet filenames] objectAtIndex: 0]]; } } - (IBAction) VideoMatrixChanged: (id) sender; { - if( ![fVideoMatrix selectedRow] ) + if( ![fRipVideoMatrix isEnabled] ) { - [fCustomBitrateField setEnabled: YES]; - [fTargetSizeField setEnabled: NO]; + [fRipCustomField setEnabled: NO]; + [fRipTargetField setEnabled: NO]; + return; + } + + if( ![fRipVideoMatrix selectedRow] ) + { + [fRipCustomField setEnabled: YES]; + [fRipTargetField setEnabled: NO]; } else { - [fCustomBitrateField setEnabled: NO]; - [fTargetSizeField setEnabled: YES]; - [fTargetSizeField UpdateBitrate]; + [fRipCustomField setEnabled: NO]; + [fRipTargetField setEnabled: YES]; + [fRipTargetField UpdateBitrate]; } } @@ -141,35 +228,42 @@ { if( returnCode == NSOKButton ) { - [fFileField setStringValue: [sheet filename]]; + [fRipFileField2 setStringValue: [sheet filename]]; + [self FormatPopUpChanged: self]; } } - (IBAction) Scan: (id) sender { + [fScMatrix setEnabled: NO]; + [fScDetectedPopUp setEnabled: NO]; + [fScFolderField setEnabled: NO]; + [fScBrowseButton setEnabled: NO]; + [fScProgress setIndeterminate: YES]; + [fScProgress startAnimation: self]; + [fScOpenButton setEnabled: NO]; + [fScStatusField setStringValue: _( @"Opening device..." )]; + /* Ask libhb to start scanning the specified volume */ - - if( ![fScanMatrix selectedRow] ) + if( ![fScMatrix selectedRow] ) { /* DVD drive */ - HBScanDevice( fHandle, - (char*) [[fDVDPopUp titleOfSelectedItem] cString], - 0 ); + HBScanDVD( fHandle, + [[fScDetectedPopUp titleOfSelectedItem] cString], 0 ); } else { /* DVD folder */ - HBScanDevice( fHandle, - (char*) [[fDVDFolderField stringValue] cString], - 0 ); + HBScanDVD( fHandle, + [[fScFolderField stringValue] cString], 0 ); } } - (IBAction) ShowPicturePanel: (id) sender { HBTitle * title = (HBTitle*) - HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] ); - + HBListItemAt( fTitleList, [fRipTitlePopUp indexOfSelectedItem] ); + [fPictureGLView SetTitle: title]; fPicture = 0; @@ -180,7 +274,7 @@ [fWidthStepper setMinValue: 16]; [fWidthStepper setMaxValue: title->outWidthMax]; [fWidthStepper setIntValue: title->outWidth]; - [fWidthField setIntValue: title->outWidth]; + [fWidthField2 setIntValue: title->outWidth]; [fDeinterlaceCheck setState: title->deinterlace ? NSOnState : NSOffState]; [fTopStepper setValueWraps: NO]; @@ -188,40 +282,38 @@ [fTopStepper setMinValue: 0]; [fTopStepper setMaxValue: title->inHeight / 4]; [fTopStepper setIntValue: title->topCrop]; - [fTopField setIntValue: title->topCrop]; + [fTopField2 setIntValue: title->topCrop]; [fBottomStepper setValueWraps: NO]; [fBottomStepper setIncrement: 2]; [fBottomStepper setMinValue: 0]; [fBottomStepper setMaxValue: title->inHeight / 4]; [fBottomStepper setIntValue: title->bottomCrop]; - [fBottomField setIntValue: title->bottomCrop]; + [fBottomField2 setIntValue: title->bottomCrop]; [fLeftStepper setValueWraps: NO]; [fLeftStepper setIncrement: 2]; [fLeftStepper setMinValue: 0]; [fLeftStepper setMaxValue: title->inWidth / 4]; [fLeftStepper setIntValue: title->leftCrop]; - [fLeftField setIntValue: title->leftCrop]; + [fLeftField2 setIntValue: title->leftCrop]; [fRightStepper setValueWraps: NO]; [fRightStepper setIncrement: 2]; [fRightStepper setMinValue: 0]; [fRightStepper setMaxValue: title->inWidth / 4]; [fRightStepper setIntValue: title->rightCrop]; - [fRightField setIntValue: title->rightCrop]; + [fRightField2 setIntValue: title->rightCrop]; [fPreviousButton setEnabled: NO]; [fNextButton setEnabled: YES]; - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "Final size: %dx%d", - title->outWidth, title->outHeight ); - [fInfoField setStringValue: [NSString stringWithCString: string]]; + [fInfoField setStringValue: [NSString stringWithFormat: + _( @"Final size: %dx%d" ), title->outWidth, title->outHeight] ]; /* Resize the panel */ NSSize newSize; /* XXX */ newSize.width = 762 /*fPicturePanelSize.width*/ + title->outWidthMax - 720; - newSize.height = 740 /*fPicturePanelSize.height*/ + + newSize.height = 755 /*fPicturePanelSize.height*/ + title->outHeightMax - 576; [fPicturePanel setContentSize: newSize]; @@ -240,45 +332,45 @@ - (IBAction) Rip: (id) sender { /* Rip or Cancel ? */ - if( [[fRipButton title] compare: @"Cancel" ] == NSOrderedSame ) + if( [[fRipRipButton title] compare: _( @"Cancel" ) ] + == NSOrderedSame ) { [self Cancel: self]; return; } - - if( [fCustomBitrateField intValue] < 256 ) + + if( [fRipCustomField intValue] < 64 ) { - NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops", - nil, nil, fWindow, self, nil, nil, nil, - @"Video bitrate is too low !" ); + NSBeginCriticalAlertSheet( _( @"Invalid video bitrate" ), + _( @"Ooops" ), nil, nil, fWindow, self, nil, nil, nil, + _( @"Video bitrate is too low." ) ); return; } - if( [fCustomBitrateField intValue] > 8192 ) + if( [fRipCustomField intValue] > 8192 ) { - NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops", - nil, nil, fWindow, self, nil, nil, nil, - @"Video bitrate is too high !" ); + NSBeginCriticalAlertSheet( _( @"Invalid video bitrate" ), + _( @"Ooops" ), nil, nil, fWindow, self, nil, nil, nil, + _( @"Video bitrate is too high." ) ); return; } - if( [fLanguagePopUp indexOfSelectedItem] == - [fSecondaryLanguagePopUp indexOfSelectedItem] ) + if( [fRipLang1PopUp indexOfSelectedItem] == + [fRipLang2PopUp indexOfSelectedItem] ) { - NSBeginCriticalAlertSheet( @"Invalid secondary language", - @"Ooops", nil, nil, fWindow, self, nil, nil, nil, - @"Do you _really_ want to encode the same audio track twice?" ); + NSBeginCriticalAlertSheet( _( @"Invalid secondary language" ), + _( @"Ooops" ), nil, nil, fWindow, self, nil, nil, nil, + _( @"You can't encode the same audio track twice." ) ); return; } - FILE * file; - if( ( file = fopen( [[fFileField stringValue] cString], "r" ) ) ) + if( [[NSFileManager defaultManager] fileExistsAtPath: + [fRipFileField2 stringValue]] ) { - fclose( file ); - NSBeginCriticalAlertSheet( @"File already exists", - @"Nooo!", @"Yes, go ahead", nil, fWindow, self, + NSBeginCriticalAlertSheet( _( @"File already exists" ), + _( @"No" ), _( @"Yes" ), nil, fWindow, self, @selector( OverwriteAlertDone:returnCode:contextInfo: ), - nil, nil, - [NSString stringWithFormat: @"Do you want to overwrite %s?", - [[fFileField stringValue] cString]] ); + nil, nil, [NSString stringWithFormat: + _( @"Do you want to overwrite %@?" ), + [fRipFileField2 stringValue]] ); return; } @@ -297,40 +389,68 @@ - (void) _Rip { /* Get the specified title & audio track(s) */ - HBTitle * title = (HBTitle*) - HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] ); - HBAudio * audio1 = (HBAudio*) - HBListItemAt( title->audioList, - [fLanguagePopUp indexOfSelectedItem] ); - HBAudio * audio2 = (HBAudio*) - HBListItemAt( title->audioList, - [fSecondaryLanguagePopUp indexOfSelectedItem] ); + HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, + [fRipTitlePopUp indexOfSelectedItem] ); + HBAudio * audio1 = (HBAudio*) HBListItemAt( title->audioList, + [fRipLang1PopUp indexOfSelectedItem] ); + HBAudio * audio2 = (HBAudio*) HBListItemAt( title->audioList, + [fRipLang2PopUp indexOfSelectedItem] ); /* Use user settings */ - title->file = strdup( [[fFileField stringValue] cString] ); - title->bitrate = [fCustomBitrateField intValue]; - title->twoPass = ( [fTwoPassCheck state] == NSOnState ); - title->codec = ( [[fVideoCodecPopUp titleOfSelectedItem] compare: - @"MPEG-4 (Ffmpeg)"] == NSOrderedSame ) ? - HB_CODEC_FFMPEG : HB_CODEC_XVID; - audio1->outBitrate = [[fAudioBitratePopUp titleOfSelectedItem] + title->file = strdup( [[fRipFileField2 stringValue] cString] ); + title->bitrate = [fRipCustomField intValue]; + title->twoPass = ( [fRipTwoPassCheck state] == NSOnState ); + + int format = [fRipFormatPopUp indexOfSelectedItem]; + int codec = [fRipEncoderPopUp indexOfSelectedItem]; + title->mux = ( !format ) ? HB_MUX_MP4 : ( ( format == 3 ) ? + HB_MUX_OGM : HB_MUX_AVI ); + title->codec = ( format == 2 ) ? HB_CODEC_X264 : ( ( !codec ) ? + HB_CODEC_FFMPEG : HB_CODEC_XVID ); + + audio1->outBitrate = [[fRipAudBitPopUp titleOfSelectedItem] intValue]; + audio1->codec = ( !format ) ? HB_CODEC_AAC : ( ( format == 3 ) ? + HB_CODEC_VORBIS : HB_CODEC_MP3 );; + HBListAdd( title->ripAudioList, audio1 ); if( audio2 ) { - audio2->outBitrate = - [[fAudioBitratePopUp titleOfSelectedItem] intValue]; + audio2->outBitrate = [[fRipAudBitPopUp + titleOfSelectedItem] intValue]; + audio2->codec = ( !format ) ? HB_CODEC_AAC : ( ( format == 3 ) ? + HB_CODEC_VORBIS : HB_CODEC_MP3 ); + HBListAdd( title->ripAudioList, audio2 ); } + /* Disable interface */ + [fRipTitlePopUp setEnabled: NO]; + [fRipFormatPopUp setEnabled: NO]; + [fRipVideoMatrix setEnabled: NO]; + [fRipCustomField setEnabled: NO]; + [fRipTargetField setEnabled: NO]; + [fRipTwoPassCheck setEnabled: NO]; + [fRipCropButton setEnabled: NO]; + [fRipLang1PopUp setEnabled: NO]; + [fRipLang2PopUp setEnabled: NO]; + [fRipAudBitPopUp setEnabled: NO]; + [fRipFileField2 setEnabled: NO]; + [fRipEncoderPopUp setEnabled: NO]; + [fRipBrowseButton setEnabled: NO]; + [fRipPauseButton setEnabled: YES]; + [fRipRipButton setTitle: _( @"Cancel" )]; + [fRipProgress setIndeterminate: YES]; + [fRipProgress startAnimation: self];; + /* Let libhb do the job */ - HBStartRip( fHandle, title, audio1, audio2 ); + HBStartRip( fHandle, title ); } - (IBAction) Cancel: (id) sender { - NSBeginCriticalAlertSheet( @"Cancel - Are you sure?", - @"Nooo, keep going!", @"Yep, stop it", nil, fWindow, self, - @selector( _Cancel:returnCode:contextInfo: ), - nil, nil, @"Encoding won't be recoverable." ); + NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ), + _( @"No" ), _( @"Yes" ), nil, fWindow, self, + @selector( _Cancel:returnCode:contextInfo: ), nil, nil, + _( @"Encoding won't be recoverable." ) ); } - (void) _Cancel: (NSWindow *) sheet @@ -338,23 +458,31 @@ { if( returnCode == NSAlertAlternateReturn ) { + if( [[fRipPauseButton title] compare: _( @"Resume" ) ] + == NSOrderedSame ) + { + HBResumeRip( fHandle ); + } HBStopRip( fHandle ); } } - (IBAction) Pause: (id) sender { - if( [[fPauseButton title] compare: @"Resume" ] == NSOrderedSame ) + if( [[fRipPauseButton title] compare: _( @"Resume" ) ] + == NSOrderedSame ) { [self Resume: self]; return; } + [fRipPauseButton setTitle: _( @"Resume" )]; HBPauseRip( fHandle ); } - (IBAction) Resume: (id) sender { + [fRipPauseButton setTitle: _( @"Pause" )]; HBResumeRip( fHandle ); } @@ -397,7 +525,7 @@ - (IBAction) UpdatePicture: (id) sender { HBTitle * title = (HBTitle*) - HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] ); + HBListItemAt( fTitleList, [fRipTitlePopUp indexOfSelectedItem] ); title->outWidth = [fWidthStepper intValue]; title->deinterlace = ( [fDeinterlaceCheck state] == NSOnState ); title->topCrop = [fTopStepper intValue]; @@ -412,298 +540,40 @@ [fBottomStepper setIntValue: title->bottomCrop]; [fLeftStepper setIntValue: title->leftCrop]; [fRightStepper setIntValue: title->rightCrop]; - [fWidthField setIntValue: [fWidthStepper intValue]]; - [fTopField setIntValue: [fTopStepper intValue]]; - [fBottomField setIntValue: [fBottomStepper intValue]]; - [fLeftField setIntValue: [fLeftStepper intValue]]; - [fRightField setIntValue: [fRightStepper intValue]]; - - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "Final size: %dx%d", - title->outWidth, title->outHeight ); - [fInfoField setStringValue: [NSString stringWithCString: string]]; + [fWidthField2 setIntValue: [fWidthStepper intValue]]; + [fTopField2 setIntValue: [fTopStepper intValue]]; + [fBottomField2 setIntValue: [fBottomStepper intValue]]; + [fLeftField2 setIntValue: [fLeftStepper intValue]]; + [fRightField2 setIntValue: [fRightStepper intValue]]; + + [fInfoField setStringValue: [NSString stringWithFormat: + _( @"Final size: %dx%d" ), title->outWidth, title->outHeight]]; } -- (void) UpdateIntf: (NSTimer *) timer +- (IBAction) AutoCrop: (id) sender { - if( fDie ) - { - [timer invalidate]; - return; - } - - int modeChanged; - HBStatus status; - - modeChanged = HBGetStatus( fHandle, &status ); - - switch( status.mode ) - { - case HB_MODE_NEED_DEVICE: - break; - - case HB_MODE_SCANNING: - { - if( modeChanged ) - { - [fScanMatrix setEnabled: NO]; - [fDVDPopUp setEnabled: NO]; - [fDVDFolderField setEnabled: NO]; - [fScanBrowseButton setEnabled: NO]; - [fScanProgress startAnimation: self]; - [fScanButton setEnabled: NO]; - } - - char string[1024]; memset( string, 0, 1024 ); - if( status.scannedTitle ) - { - sprintf( string, "Scanning title %d...", - status.scannedTitle ); - } - else - { - sprintf( string, "Opening device..." ); - } - [fScanStatusField setStringValue: - [NSString stringWithCString: string]]; - - break; - } - - case HB_MODE_INVALID_DEVICE: - { - if( !modeChanged ) - break; - - [fScanMatrix setEnabled: YES]; - [self ScanMatrixChanged: self]; - [fScanProgress stopAnimation: self]; - [fScanButton setEnabled: YES]; - - [fScanStatusField setStringValue: - @"Invalid volume, try again" ]; - break; - } - - case HB_MODE_READY_TO_RIP: - { - if( !modeChanged ) - break; - - fTitleList = status.titleList; - - /* Show a temporary empty view while the window - resizing animation */ - [fWindow setContentView: fTempView ]; - - /* Actually resize it */ - NSRect newFrame; - newFrame = [NSWindow contentRectForFrameRect: [fWindow frame] - styleMask: [fWindow styleMask]]; - newFrame.origin.y += newFrame.size.height - - [fRipView frame].size.height; - newFrame.size.height = [fRipView frame].size.height; - newFrame.size.width = [fRipView frame].size.width; - newFrame = [NSWindow frameRectForContentRect: newFrame - styleMask: [fWindow styleMask]]; - [fWindow setFrame: newFrame display: YES animate: YES]; - - /* Show the new GUI */ - [fWindow setContentView: fRipView ]; - [fPauseButton setEnabled: NO]; - - [fTitlePopUp removeAllItems]; - HBTitle * title; - for( int i = 0; i < HBListCountItems( fTitleList ); i++ ) - { - title = (HBTitle*) HBListItemAt( fTitleList, i ); - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "%d - %02dh%02dm%02ds", - title->index, title->length / 3600, - ( title->length % 3600 ) / 60, - title->length % 60 ); - [[fTitlePopUp menu] addItemWithTitle: - [NSString stringWithCString: string] - action: nil keyEquivalent: @""]; - } - [self TitlePopUpChanged: self]; - - break; - } - - case HB_MODE_ENCODING: - { - if( modeChanged ) - { - [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]; - [fFileField setEnabled: NO]; - [fFileBrowseButton setEnabled: NO]; - [fPauseButton setEnabled: YES]; - [fPauseButton setTitle: @"Pause"]; - [fRipButton setTitle: @"Cancel"]; - } - - if( !status.position ) - { - [fRipStatusField setStringValue: @"Starting..."]; - [fRipProgress setIndeterminate: YES]; - [fRipProgress startAnimation: self];; - } - else - { - char string[1024]; - memset( string, 0, 1024 ); - sprintf( string, "Encoding: %.2f %% (pass %d of %d)", - 100 * status.position, status.pass, - status.passCount ); - [fRipStatusField setStringValue: - [NSString stringWithCString: string]]; - memset( string, 0, 1024 ); - sprintf( string, "Speed: %.2f fps (avg %.2f fps, " - "%02dh%02dm%02ds remaining)", - status.frameRate, status.avFrameRate, - status.remainingTime / 3600, - ( status.remainingTime / 60 ) % 60, - status.remainingTime % 60 ); - [fRipInfoField setStringValue: - [NSString stringWithCString: string]]; - - [fRipProgress setIndeterminate: NO]; - [fRipProgress setDoubleValue: 100 * status.position]; - } - - break; - } - - case HB_MODE_PAUSED: - { - if( !modeChanged ) - break; - - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "Encoding: %.2f %% (PAUSED)", - 100 * status.position ) ; - [fRipStatusField setStringValue: - [NSString stringWithCString: string]]; - [fRipInfoField setStringValue: @""]; - - [fRipProgress setDoubleValue: 100 * status.position]; - - [fPauseButton setTitle: @"Resume"]; - break; - } - - case HB_MODE_STOPPING: - if( !modeChanged ) - break; - - [fRipStatusField setStringValue: @"Stopping..."]; - [fRipInfoField setStringValue: @""]; - [fRipProgress setIndeterminate: YES]; - [fRipProgress startAnimation: self];; - break; - - case HB_MODE_DONE: - case HB_MODE_CANCELED: - case HB_MODE_ERROR: - if( !modeChanged ) - break; - - /* Warn the finder to update itself */ - [[NSWorkspace sharedWorkspace] noteFileSystemChanged: - [fFileField stringValue]]; - - [fRipProgress setIndeterminate: NO]; - [fRipInfoField setStringValue: @""]; - - if( status.mode == HB_MODE_DONE ) - { - [fRipProgress setDoubleValue: 100]; - [fRipStatusField setStringValue: @"Done." ]; - NSBeep(); - [NSApp requestUserAttention: NSInformationalRequest]; - [NSApp beginSheet: fDonePanel - modalForWindow: fWindow modalDelegate: nil - didEndSelector: nil contextInfo: nil]; - [NSApp runModalForWindow: fDonePanel]; - [NSApp endSheet: fDonePanel]; - [fDonePanel orderOut: self]; - } - else if( status.mode == HB_MODE_CANCELED ) - { - [fRipProgress setDoubleValue: 0]; - [fRipStatusField setStringValue: @"Canceled." ]; - } - else - { - [fRipProgress setDoubleValue: 0]; - switch( status.error ) - { - 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; - } - } - - [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]; - [fFileField setEnabled: YES]; - [fFileBrowseButton setEnabled: YES]; - [fPauseButton setEnabled: NO]; - [fPauseButton setTitle: @"Pause"]; - [fRipButton setTitle: @"Rip"]; - - [self VideoMatrixChanged: self]; + HBTitle * title = (HBTitle*) + HBListItemAt( fTitleList, [fRipTitlePopUp indexOfSelectedItem] ); + title->topCrop = title->autoTopCrop; + title->bottomCrop = title->autoBottomCrop; + title->leftCrop = title->autoLeftCrop; + title->rightCrop = title->autoRightCrop; - break; + [fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE]; - default: - break; - } + [fWidthStepper setIntValue: title->outWidth]; + [fTopStepper setIntValue: title->topCrop]; + [fBottomStepper setIntValue: title->bottomCrop]; + [fLeftStepper setIntValue: title->leftCrop]; + [fRightStepper setIntValue: title->rightCrop]; + [fWidthField2 setIntValue: [fWidthStepper intValue]]; + [fTopField2 setIntValue: [fTopStepper intValue]]; + [fBottomField2 setIntValue: [fBottomStepper intValue]]; + [fLeftField2 setIntValue: [fLeftStepper intValue]]; + [fRightField2 setIntValue: [fRightStepper intValue]]; + + [fInfoField setStringValue: [NSString stringWithFormat: + _( @"Final size: %dx%d" ), title->outWidth, title->outHeight]]; } - (void) DetectDrives: (NSNotification *) notification @@ -781,10 +651,10 @@ IOObjectRelease( media_iterator ); - [fDVDPopUp removeAllItems]; + [fScDetectedPopUp removeAllItems]; for( unsigned i = 0; i < [drivesList count]; i++ ) { - [[fDVDPopUp menu] addItemWithTitle: + [[fScDetectedPopUp menu] addItemWithTitle: [drivesList objectAtIndex: i] action: nil keyEquivalent: @""]; } @@ -793,61 +663,297 @@ - (IBAction) ScanMatrixChanged: (id) sender { - if( ![fScanMatrix selectedRow] ) + if( ![fScMatrix selectedRow] ) { - [fDVDPopUp setEnabled: YES]; - [fDVDFolderField setEnabled: NO]; - [fScanBrowseButton setEnabled: NO]; - [fScanButton setEnabled: ( [fDVDPopUp selectedItem] != nil )]; + [fScDetectedPopUp setEnabled: YES]; + [fScFolderField setEnabled: NO]; + [fScBrowseButton setEnabled: NO]; + [fScOpenButton setEnabled: ( [fScDetectedPopUp selectedItem] != nil )]; } else { - [fDVDPopUp setEnabled: NO]; - [fDVDFolderField setEnabled: YES]; - [fScanBrowseButton setEnabled: YES]; - [fScanButton setEnabled: YES]; + [fScDetectedPopUp setEnabled: NO]; + [fScFolderField setEnabled: YES]; + [fScBrowseButton setEnabled: YES]; + [fScOpenButton setEnabled: YES]; } } - (IBAction) TitlePopUpChanged: (id) sender { HBTitle * title = (HBTitle*) - HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] ); + HBListItemAt( fTitleList, [fRipTitlePopUp indexOfSelectedItem] ); + + [fRipLang1PopUp removeAllItems]; + [fRipLang2PopUp removeAllItems]; - [fLanguagePopUp removeAllItems]; - [fSecondaryLanguagePopUp removeAllItems]; - HBAudio * audio; - for( int i = 0; i < HBListCountItems( title->audioList ); i++ ) + for( int i = 0; i < HBListCount( title->audioList ); i++ ) { audio = (HBAudio*) HBListItemAt( title->audioList, i ); /* We cannot use NSPopUpButton's addItemWithTitle because it checks for duplicate entries */ - [[fLanguagePopUp menu] addItemWithTitle: + [[fRipLang1PopUp menu] addItemWithTitle: [NSString stringWithCString: audio->language] action: nil keyEquivalent: @""]; - [[fSecondaryLanguagePopUp menu] addItemWithTitle: + [[fRipLang2PopUp menu] addItemWithTitle: [NSString stringWithCString: audio->language] action: nil keyEquivalent: @""]; } - [fSecondaryLanguagePopUp addItemWithTitle: @"None"]; - [fSecondaryLanguagePopUp selectItemWithTitle: @"None"]; - [fSecondaryLanguagePopUp setEnabled: - ( HBListCountItems( title->audioList ) > 1 )]; + [fRipLang2PopUp addItemWithTitle: _( @"None" )]; + [fRipLang2PopUp selectItemWithTitle: _( @"None" )]; + [fRipLang2PopUp setEnabled: + ( HBListCount( title->audioList ) > 1 )]; - [fTargetSizeField SetHBTitle: title]; - if( [fVideoMatrix selectedRow] ) + [fRipTargetField SetHBTitle: title]; + if( [fRipVideoMatrix selectedRow] ) { - [fTargetSizeField UpdateBitrate]; + [fRipTargetField UpdateBitrate]; } } +- (IBAction) FormatPopUpChanged: (id) sender +{ + /* Headers size changes depending on the format, so let's + recalculate the bitrate if necessary */ + if( [fRipVideoMatrix selectedRow] ) + { + [fRipTargetField UpdateBitrate]; + } + + /* Add/replace to the correct extension */ + NSString * string = [fRipFileField2 stringValue]; + int format = [fRipFormatPopUp indexOfSelectedItem]; + if( [string characterAtIndex: [string length] - 4] == '.' ) + { + [fRipFileField2 setStringValue: [NSString stringWithFormat: + @"%@.%s", [string substringToIndex: [string length] - 4], + ( !format ) ? "mp4" : ( ( format == 3 ) ? + "ogm" : "avi" )]]; + } + else + { + [fRipFileField2 setStringValue: [NSString stringWithFormat: + @"%@.%s", string, ( !format ) ? "mp4" : + ( ( format == 3 ) ? "ogm" : "avi" )]]; + } + + if( format == 2 ) + { + /* Can't set X264 bitrate */ + [fRipEncoderPopUp setEnabled: NO]; + [fRipVideoMatrix setEnabled: NO]; + [fRipTwoPassCheck setEnabled: NO]; + + [fRipAudBitPopUp setEnabled: YES]; + } + else if( format == 3 ) + { + [fRipEncoderPopUp setEnabled: YES]; + [fRipVideoMatrix setEnabled: YES]; + [fRipTwoPassCheck setEnabled: YES]; + + /* Can't set Vorbis bitrate */ + [fRipAudBitPopUp setEnabled: NO]; + } + else + { + [fRipEncoderPopUp setEnabled: YES]; + [fRipVideoMatrix setEnabled: YES]; + [fRipTwoPassCheck setEnabled: YES]; + [fRipAudBitPopUp setEnabled: YES]; + } + [self VideoMatrixChanged: self]; +} + - (IBAction) AudioPopUpChanged: (id) sender { - if( [fVideoMatrix selectedRow] ) + /* Recalculate the bitrate */ + if( [fRipVideoMatrix selectedRow] ) + { + [fRipTargetField UpdateBitrate]; + } +} + +/******************* + * libhb callbacks * + *******************/ +static void _Scanning( void * data, int title, int titleCount ) +{ + HBController * controller = (HBController*) data; + controller->fTitle = title; + controller->fTitleCount = titleCount; + [controller performSelectorOnMainThread: @selector(Scanning:) + withObject: nil waitUntilDone: YES]; +} +- (void) Scanning: (id) sender +{ + [fScProgress stopAnimation: self]; + [fScProgress setIndeterminate: NO]; + [fScProgress setDoubleValue: 100.0 * fTitle / fTitleCount]; + + [fScStatusField setStringValue: [NSString stringWithFormat: + _( @"Scanning title %d of %d..." ), fTitle, fTitleCount]]; +} + +static void _ScanDone( void * data, HBList * titleList ) +{ + HBController * controller = (HBController*) data; + controller->fTitleList = titleList; + [controller performSelectorOnMainThread: @selector(ScanDone:) + withObject: nil waitUntilDone: YES]; +} +- (void) ScanDone: (id) sender +{ + if( !fTitleList ) { - [fTargetSizeField UpdateBitrate]; + [fScMatrix setEnabled: YES]; + [self ScanMatrixChanged: self]; + [fScProgress stopAnimation: self]; + [fScProgress setIndeterminate: NO]; + [fScOpenButton setEnabled: YES]; + [fScStatusField setStringValue: + _( @"Invalid volume, try again" ) ]; + return; + } + + /* Show a temporary empty view while the window + resizing animation */ + [fWindow setContentView: fTempView ]; + + /* Actually resize it */ + NSRect newFrame; + newFrame = [NSWindow contentRectForFrameRect: [fWindow frame] + styleMask: [fWindow styleMask]]; + newFrame.origin.y += newFrame.size.height - + [fRipView frame].size.height; + newFrame.size.height = [fRipView frame].size.height; + newFrame.size.width = [fRipView frame].size.width; + newFrame = [NSWindow frameRectForContentRect: newFrame + styleMask: [fWindow styleMask]]; + [fWindow setFrame: newFrame display: YES animate: YES]; + + /* Show the new GUI */ + [fWindow setContentView: fRipView ]; + [fRipPauseButton setEnabled: NO]; + + [fRipTitlePopUp removeAllItems]; + HBTitle * title; + for( int i = 0; i < HBListCount( fTitleList ); i++ ) + { + title = (HBTitle*) HBListItemAt( fTitleList, i ); + [[fRipTitlePopUp menu] addItemWithTitle: + [NSString stringWithFormat: @"%d - %02dh%02dm%02ds", + title->index, title->length / 3600, ( title->length % 3600 ) + / 60, title->length % 60] action: nil keyEquivalent: @""]; + } + [self TitlePopUpChanged: self]; +} + +static void _Encoding( void * data, float position, int pass, + int passCount, float curFrameRate, + float avgFrameRate, int remainingTime ) +{ + HBController * controller = (HBController*) data; + controller->fPosition = position; + controller->fPass = pass; + controller->fPassCount = passCount; + controller->fCurFrameRate = curFrameRate; + controller->fAvgFrameRate = avgFrameRate; + controller->fRemainingTime = remainingTime; + [controller performSelectorOnMainThread: @selector(Encoding:) + withObject: nil waitUntilDone: YES]; +} +- (void) Encoding: (id) sender +{ + [fRipStatusField setStringValue: [NSString stringWithFormat: + _( @"Encoding: %.2f %% (pass %d of %d)" ), + 100.0 * fPosition, fPass, fPassCount]]; + [fRipInfoField setStringValue: [NSString stringWithFormat: + _( @"Speed: %.2f fps (avg %.2f fps), %02dh%02dm%02ds remaining" ), + fCurFrameRate, fAvgFrameRate, fRemainingTime / 3600, + ( fRemainingTime / 60 ) % 60, fRemainingTime % 60]]; + + [fRipProgress setIndeterminate: NO]; + [fRipProgress setDoubleValue: 100.0 * fPosition]; +} + +static void _RipDone( void * data, int result ) +{ + HBController * controller = (HBController*) data; + controller->fResult = result; + [controller performSelectorOnMainThread: @selector(RipDone:) + withObject: nil waitUntilDone: YES]; +} +- (void) RipDone: (id) sender +{ + [fRipTitlePopUp setEnabled: YES]; + [fRipFormatPopUp setEnabled: YES]; + [fRipVideoMatrix setEnabled: YES]; + [fRipTwoPassCheck setEnabled: YES]; + [fRipCropButton setEnabled: YES]; + [fRipLang1PopUp setEnabled: YES]; + [fRipLang2PopUp setEnabled: YES]; + [fRipAudBitPopUp setEnabled: YES]; + [fRipFileField2 setEnabled: YES]; + [fRipBrowseButton setEnabled: YES]; + [fRipEncoderPopUp setEnabled: YES]; + [fRipPauseButton setEnabled: NO]; + [fRipPauseButton setTitle: _( @"Pause" )]; + [fRipRipButton setTitle: _( @"Rip" )]; + [fRipProgress setIndeterminate: NO]; + [fRipProgress setDoubleValue: 0.0]; + [self VideoMatrixChanged: self]; + + switch( fResult ) + { + case HB_SUCCESS: + [fRipStatusField setStringValue: _( @"Rip completed." )]; + [fRipInfoField setStringValue: @""]; + NSBeep(); + [NSApp requestUserAttention: NSInformationalRequest]; + [NSApp beginSheet: fDonePanel + modalForWindow: fWindow modalDelegate: nil + didEndSelector: nil contextInfo: nil]; + [NSApp runModalForWindow: fDonePanel]; + [NSApp endSheet: fDonePanel]; + [fDonePanel orderOut: self]; + break; + case HB_CANCELED: + [fRipStatusField setStringValue: _( @"Canceled." )]; + [fRipInfoField setStringValue: @""]; + break; + case HB_ERROR_A52_SYNC: + [fRipStatusField setStringValue: @"Error."]; + [fRipInfoField setStringValue: @"Corrupted AC3 data"]; + break; + case HB_ERROR_AVI_WRITE: + [fRipStatusField setStringValue: @"Error."]; + [fRipInfoField setStringValue: @"Write error"]; + break; + case HB_ERROR_DVD_OPEN: + [fRipStatusField setStringValue: @"Error."]; + [fRipInfoField setStringValue: @"Could not open the DVD"]; + break; + case HB_ERROR_DVD_READ: + [fRipStatusField setStringValue: @"Error."]; + [fRipInfoField setStringValue: @"DVD read error"]; + break; + case HB_ERROR_MP3_INIT: + [fRipStatusField setStringValue: @"Error."]; + [fRipInfoField setStringValue: + @"MP3 encoder initialization failed"]; + break; + case HB_ERROR_MP3_ENCODE: + [fRipStatusField setStringValue: @"Error."]; + [fRipInfoField setStringValue: @"MP3 encoder failed"]; + break; + case HB_ERROR_MPEG4_INIT: + [fRipStatusField setStringValue: @"Error."]; + [fRipInfoField setStringValue: + @"MPEG4 encoder initialization failed"]; + break; } } diff --git a/macosx/English.lproj/InfoPlist.strings b/macosx/English.lproj/InfoPlist.strings Binary files differindex ce3b28a62..714d974fa 100644 --- a/macosx/English.lproj/InfoPlist.strings +++ b/macosx/English.lproj/InfoPlist.strings diff --git a/macosx/English.lproj/MainMenu.nib/classes.nib b/macosx/English.lproj/MainMenu.nib/classes.nib index 161d51070..b77248ae6 100644 --- a/macosx/English.lproj/MainMenu.nib/classes.nib +++ b/macosx/English.lproj/MainMenu.nib/classes.nib @@ -4,17 +4,23 @@ { ACTIONS = { AudioPopUpChanged = id; + AutoCrop = id; BrowseDVD = id; BrowseFile = id; Cancel = id; ClosePanel = id; + Encoding = id; + FormatPopUpChanged = id; NextPicture = id; Pause = id; PreviousPicture = id; Resume = id; Rip = id; + RipDone = id; Scan = id; + ScanDone = id; ScanMatrixChanged = id; + Scanning = id; ShowPicturePanel = id; TitlePopUpChanged = id; UpdatePicture = id; @@ -23,52 +29,75 @@ CLASS = HBController; LANGUAGE = ObjC; OUTLETS = { - fAudioBitratePopUp = NSPopUpButton; - fAudioCodecPopUp = NSPopUpButton; - fBottomField = NSTextField; + fAutocropButton = NSButton; + fBottomField1 = NSTextField; + fBottomField2 = NSTextField; fBottomStepper = NSStepper; - fCropButton = NSButton; - fCustomBitrateField = NSTextField; - fDVDFolderField = NSTextField; - fDVDPopUp = NSPopUpButton; + fCloseButton = NSButton; fDeinterlaceCheck = NSButton; fDonePanel = NSPanel; - fFileBrowseButton = NSButton; - fFileField = NSTextField; - fFileFormatPopUp = NSPopUpButton; fInfoField = NSTextField; - fLanguagePopUp = NSPopUpButton; - fLeftField = NSTextField; + fLeftField1 = NSTextField; + fLeftField2 = NSTextField; fLeftStepper = NSStepper; fNextButton = NSButton; fOpenGLCheck = NSButton; - fPauseButton = NSButton; fPictureGLView = HBPictureGLView; fPicturePanel = NSPanel; fPreviousButton = NSButton; - fRightField = NSTextField; + fRightField1 = NSTextField; + fRightField2 = NSTextField; fRightStepper = NSStepper; - fRipButton = NSButton; + fRipAudBitField = NSTextField; + fRipAudBitPopUp = NSPopUpButton; + fRipAudioField = NSTextField; + fRipBitrateField = NSTextField; + fRipBrowseButton = NSButton; + fRipCropButton = NSButton; + fRipCustomCell = NSButtonCell; + fRipCustomField = NSTextField; + fRipEncoderField = NSTextField; + fRipEncoderPopUp = NSPopUpButton; + fRipFileField1 = NSTextField; + fRipFileField2 = NSTextField; + fRipFormatField = NSTextField; + fRipFormatPopUp = NSPopUpButton; + fRipGeneralField = NSTextField; fRipInfoField = NSTextField; + fRipLang1Field = NSTextField; + fRipLang1PopUp = NSPopUpButton; + fRipLang2Field = NSTextField; + fRipLang2PopUp = NSPopUpButton; + fRipPauseButton = NSButton; fRipProgress = NSProgressIndicator; + fRipRipButton = NSButton; fRipStatusField = NSTextField; + fRipTargetCell = NSButtonCell; + fRipTargetField = HBTargetSizeField; + fRipTitleField = NSTextField; + fRipTitlePopUp = NSPopUpButton; + fRipTwoPassCheck = NSButton; + fRipVideoField = NSTextField; + fRipVideoMatrix = NSMatrix; fRipView = NSView; - fScanBrowseButton = NSButton; - fScanButton = NSButton; - fScanMatrix = NSMatrix; - fScanProgress = NSProgressIndicator; - fScanStatusField = NSTextField; - fScanView = NSView; - fSecondaryLanguagePopUp = NSPopUpButton; - fTargetSizeField = HBTargetSizeField; + fScBrowseButton = NSButton; + fScDetectedCell = NSButtonCell; + fScDetectedPopUp = NSPopUpButton; + fScFolderCell = NSButtonCell; + fScFolderField = NSTextField; + fScMatrix = NSMatrix; + fScOpenButton = NSButton; + fScProgress = NSProgressIndicator; + fScSelectField = NSTextField; + fScStatusField = NSTextField; + fScView = NSView; + fScWelcomeField = NSTextField; fTempView = NSView; - fTitlePopUp = NSPopUpButton; - fTopField = NSTextField; + fTopField1 = NSTextField; + fTopField2 = NSTextField; fTopStepper = NSStepper; - fTwoPassCheck = NSButton; - fVideoCodecPopUp = NSPopUpButton; - fVideoMatrix = NSMatrix; - fWidthField = NSTextField; + fWidthField1 = NSTextField; + fWidthField2 = NSTextField; fWidthStepper = NSStepper; fWindow = NSWindow; }; @@ -79,9 +108,10 @@ CLASS = HBTargetSizeField; LANGUAGE = ObjC; OUTLETS = { - fAudioBitratePopUp = NSPopUpButton; - fBitrateField = NSTextField; - fSecondaryLanguagePopUp = NSPopUpButton; + fRipAudBitPopUp = NSPopUpButton; + fRipCustomField = NSTextField; + fRipFormatPopUp = NSPopUpButton; + fRipLang2PopUp = NSPopUpButton; }; SUPERCLASS = NSTextField; }, diff --git a/macosx/English.lproj/MainMenu.nib/info.nib b/macosx/English.lproj/MainMenu.nib/info.nib index a4c078c28..80f27b803 100644 --- a/macosx/English.lproj/MainMenu.nib/info.nib +++ b/macosx/English.lproj/MainMenu.nib/info.nib @@ -3,31 +3,31 @@ <plist version="1.0"> <dict> <key>IBDocumentLocation</key> - <string>25 188 381 380 0 0 1440 878 </string> + <string>43 111 381 380 0 0 1440 878 </string> <key>IBEditorPositions</key> <dict> <key>29</key> - <string>407 469 205 44 0 0 1440 878 </string> + <string>297 654 165 44 0 0 1440 878 </string> <key>556</key> - <string>510 481 420 244 0 0 1440 878 </string> + <string>513 432 417 306 0 0 1440 878 </string> <key>583</key> - <string>648 517 144 171 0 0 1440 878 </string> - <key>589</key> - <string>510 282 420 586 0 0 1440 878 </string> + <string>573 493 144 171 0 0 1440 878 </string> + <key>689</key> + <string>513 258 418 610 0 0 1440 878 </string> </dict> <key>IBFramework Version</key> <string>349.0</string> <key>IBOpenObjects</key> <array> - <integer>556</integer> - <integer>589</integer> + <integer>689</integer> <integer>365</integer> - <integer>434</integer> - <integer>29</integer> <integer>583</integer> + <integer>29</integer> + <integer>556</integer> + <integer>434</integer> <integer>21</integer> </array> <key>IBSystem Version</key> - <string>7C107</string> + <string>7D24</string> </dict> </plist> diff --git a/macosx/English.lproj/MainMenu.nib/objects.nib b/macosx/English.lproj/MainMenu.nib/objects.nib Binary files differindex 956897bce..b088624ed 100644 --- a/macosx/English.lproj/MainMenu.nib/objects.nib +++ b/macosx/English.lproj/MainMenu.nib/objects.nib diff --git a/macosx/HandBrake.pbproj/project.pbxproj b/macosx/HandBrake.xcode/project.pbxproj index c47e0176a..6416e2c67 100644 --- a/macosx/HandBrake.pbproj/project.pbxproj +++ b/macosx/HandBrake.xcode/project.pbxproj @@ -35,9 +35,9 @@ sourceTree = "<group>"; }; 089C165DFE840E0CC02AAC07 = { - expectedFileType = text.plist.strings; fileEncoding = 10; isa = PBXFileReference; + lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; refType = 4; @@ -71,9 +71,9 @@ sourceTree = "<group>"; }; 1058C7A1FEA54F0111CA2CBB = { - expectedFileType = wrapper.framework; fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; + lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; refType = 0; @@ -106,7 +106,7 @@ //173 //174 17587328FF379C6511CA2CBB = { - expectedFileType = wrapper.application; + explicitFileType = wrapper.application; fallbackIsa = PBXFileReference; isa = PBXApplicationReference; path = HandBrake.app; @@ -185,15 +185,19 @@ sourceTree = "<group>"; }; 29B97316FDCFA39411CA2CEA = { - expectedFileType = sourcecode.cpp.objcpp; fileEncoding = 30; isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; refType = 4; sourceTree = "<group>"; }; 29B97317FDCFA39411CA2CEA = { children = ( + 4D194F36059E0FBC004A33A1, + 4D548205059E100C00AD5E02, + 4D194F37059E0FBC004A33A1, + 4D194F38059E0FBC004A33A1, 29B97318FDCFA39411CA2CEA, 4D929FED0527907200A80101, 4D69F5C80527944A00A80101, @@ -206,6 +210,8 @@ 4DDEF3B905474DCC002904DE, 4D118405053054CD00C39CA9, 089C165CFE840E0CC02AAC07, + 4D0AEC1805747B7A00FAB0FD, + 4D0AEC1C05747B8C00FAB0FD, ); isa = PBXGroup; name = Resources; @@ -224,8 +230,8 @@ sourceTree = "<group>"; }; 29B97319FDCFA39411CA2CEA = { - expectedFileType = wrapper.nib; isa = PBXFileReference; + lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; refType = 4; @@ -243,18 +249,18 @@ sourceTree = "<group>"; }; 29B97324FDCFA39411CA2CEA = { - expectedFileType = wrapper.framework; fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; + lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; refType = 0; sourceTree = "<absolute>"; }; 29B97325FDCFA39411CA2CEA = { - expectedFileType = wrapper.framework; fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; + lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; refType = 0; @@ -271,9 +277,9 @@ FRAMEWORK_SEARCH_PATHS = ""; GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ""; - LIBRARY_SEARCH_PATHS = ../core; + LIBRARY_SEARCH_PATHS = "../core ../contrib/liba52 ../contrib/libavcodec ../contrib/libdvdcss ../contrib/libdvdplay ../contrib/libdvdread ../contrib/libfaac ../contrib/libmp3lame ../contrib/libmp4v2 ../contrib/libmpeg2 ../contrib/libogg ../contrib/libvorbis ../contrib/libx264 ../contrib/libxvidcore"; OPTIMIZATION_CFLAGS = "-O3"; - OTHER_CFLAGS = "-DSYS_MACOSX"; + OTHER_CFLAGS = "-DHB_MACOSX"; OTHER_LDFLAGS = ""; PRODUCT_NAME = HandBrake; SECTORDER_FLAGS = ""; @@ -295,7 +301,7 @@ <key>CFBundleExecutable</key> <string>HandBrake</string> <key>CFBundleGetInfoString</key> - <string>HandBrake 0.5.2 - By Eric Petit <[email protected]></string> + <string>HandBrake 0.5.2+ - By Eric Petit <[email protected]></string> <key>CFBundleIconFile</key> <string>HandBrake.icns</string> <key>CFBundleIdentifier</key> @@ -307,11 +313,11 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>0.5.2</string> + <string>0.5.2+</string> <key>CFBundleSignature</key> <string>HB##</string> <key>CFBundleVersion</key> - <string>0.5.2</string> + <string>0.5.2+</string> <key>NSMainNibFile</key> <string>MainMenu</string> <key>NSPrincipalClass</key> @@ -375,6 +381,12 @@ 4DEB2025052B055F00C39CA9, 4DDE9725052B7B2B00C39CA9, 4DDEF3BA05474DCC002904DE, + 4D0AEC1905747B7A00FAB0FD, + 4D0AEC1D05747B8C00FAB0FD, + 4D194F39059E0FBC004A33A1, + 4D194F3A059E0FBC004A33A1, + 4D194F3B059E0FBC004A33A1, + 4D548206059E100C00AD5E02, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -394,11 +406,12 @@ ); buildSettings = { COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_DYNAMIC_NO_PIC = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - OPTIMIZATION_CFLAGS = "-O0"; + GCC_OPTIMIZATION_LEVEL = 3; + LIBRARY_SEARCH_PATHS = "../core ../contrib/lib"; + OPTIMIZATION_CFLAGS = "-O3"; ZERO_LINK = YES; }; isa = PBXBuildStyle; @@ -425,9 +438,37 @@ //4D2 //4D3 //4D4 + 4D0AEC1805747B7A00FAB0FD = { + isa = PBXFileReference; + lastKnownFileType = archive.ar; + name = libfaac.a; + path = ../contrib/libfaac/libfaac.a; + refType = 2; + sourceTree = SOURCE_ROOT; + }; + 4D0AEC1905747B7A00FAB0FD = { + fileRef = 4D0AEC1805747B7A00FAB0FD; + isa = PBXBuildFile; + settings = { + }; + }; + 4D0AEC1C05747B8C00FAB0FD = { + isa = PBXFileReference; + lastKnownFileType = archive.ar; + name = libmp4v2.a; + path = ../contrib/libmp4v2/libmp4v2.a; + refType = 2; + sourceTree = SOURCE_ROOT; + }; + 4D0AEC1D05747B8C00FAB0FD = { + fileRef = 4D0AEC1C05747B8C00FAB0FD; + isa = PBXBuildFile; + settings = { + }; + }; 4D118405053054CD00C39CA9 = { - expectedFileType = image.icns; isa = PBXFileReference; + lastKnownFileType = image.icns; path = HandBrake.icns; refType = 4; sourceTree = "<group>"; @@ -438,18 +479,60 @@ settings = { }; }; + 4D194F36059E0FBC004A33A1 = { + isa = PBXFileReference; + lastKnownFileType = archive.ar; + name = libvorbis.a; + path = ../contrib/libvorbis/libvorbis.a; + refType = 2; + sourceTree = SOURCE_ROOT; + }; + 4D194F37059E0FBC004A33A1 = { + isa = PBXFileReference; + lastKnownFileType = archive.ar; + name = libvorbisenc.a; + path = ../contrib/libvorbis/libvorbisenc.a; + refType = 2; + sourceTree = SOURCE_ROOT; + }; + 4D194F38059E0FBC004A33A1 = { + isa = PBXFileReference; + lastKnownFileType = archive.ar; + name = libx264.a; + path = ../contrib/libx264/libx264.a; + refType = 2; + sourceTree = SOURCE_ROOT; + }; + 4D194F39059E0FBC004A33A1 = { + fileRef = 4D194F36059E0FBC004A33A1; + isa = PBXBuildFile; + settings = { + }; + }; + 4D194F3A059E0FBC004A33A1 = { + fileRef = 4D194F37059E0FBC004A33A1; + isa = PBXBuildFile; + settings = { + }; + }; + 4D194F3B059E0FBC004A33A1 = { + fileRef = 4D194F38059E0FBC004A33A1; + isa = PBXBuildFile; + settings = { + }; + }; 4D358C000534A91300D654EB = { - expectedFileType = sourcecode.c.h; fileEncoding = 30; isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; path = TargetSizeField.h; refType = 4; sourceTree = "<group>"; }; 4D358C010534A91300D654EB = { - expectedFileType = sourcecode.cpp.objcpp; fileEncoding = 30; isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.objcpp; path = TargetSizeField.mm; refType = 4; sourceTree = "<group>"; @@ -466,6 +549,20 @@ settings = { }; }; + 4D548205059E100C00AD5E02 = { + isa = PBXFileReference; + lastKnownFileType = archive.ar; + name = libogg.a; + path = ../contrib/libogg/libogg.a; + refType = 2; + sourceTree = SOURCE_ROOT; + }; + 4D548206059E100C00AD5E02 = { + fileRef = 4D548205059E100C00AD5E02; + isa = PBXBuildFile; + settings = { + }; + }; 4D6615EA05288C2300A80101 = { fileRef = 4DF3C8CB052889CD00A80101; isa = PBXBuildFile; @@ -473,60 +570,60 @@ }; }; 4D69F5C80527944A00A80101 = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = liba52.a; - path = /usr/local/lib/liba52.a; - refType = 0; - sourceTree = "<absolute>"; + path = ../contrib/liba52/liba52.a; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4D69F5C90527944A00A80101 = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = libavcodec.a; - path = /usr/local/lib/libavcodec.a; - refType = 0; - sourceTree = "<absolute>"; + path = ../contrib/libavcodec/libavcodec.a; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4D69F5CA0527944A00A80101 = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = libdvdcss.a; - path = /usr/local/lib/libdvdcss.a; - refType = 0; - sourceTree = "<absolute>"; + path = ../contrib/libdvdcss/libdvdcss.a; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4D69F5CB0527944A00A80101 = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = libdvdplay.a; - path = /usr/local/lib/libdvdplay.a; - refType = 0; - sourceTree = "<absolute>"; + path = ../contrib/libdvdplay/libdvdplay.a; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4D69F5CC0527944A00A80101 = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = libdvdread.a; - path = /usr/local/lib/libdvdread.a; - refType = 0; - sourceTree = "<absolute>"; + path = ../contrib/libdvdread/libdvdread.a; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4D69F5CD0527944A00A80101 = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = libmp3lame.a; - path = /usr/local/lib/libmp3lame.a; - refType = 0; - sourceTree = "<absolute>"; + path = ../contrib/libmp3lame/libmp3lame.a; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4D69F5CE0527944A00A80101 = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = libmpeg2.a; - path = /usr/local/lib/libmpeg2.a; - refType = 0; - sourceTree = "<absolute>"; + path = ../contrib/libmpeg2/libmpeg2.a; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4D69F5CF0527944A00A80101 = { fileRef = 4D69F5C80527944A00A80101; @@ -571,17 +668,17 @@ }; }; 4D85758E052B78E300C39CA9 = { - expectedFileType = sourcecode.cpp.objcpp; fileEncoding = 30; isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.objcpp; path = PictureGLView.mm; refType = 4; sourceTree = "<group>"; }; 4D85758F052B78E300C39CA9 = { - expectedFileType = sourcecode.c.h; fileEncoding = 30; isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; path = PictureGLView.h; refType = 4; sourceTree = "<group>"; @@ -599,12 +696,12 @@ }; }; 4D929FED0527907200A80101 = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = libhb.a; path = ../core/libhb.a; - refType = 4; - sourceTree = "<group>"; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4D929FEE0527907200A80101 = { fileRef = 4D929FED0527907200A80101; @@ -613,9 +710,9 @@ }; }; 4DDE9724052B7B2B00C39CA9 = { - expectedFileType = wrapper.framework; fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; + lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; refType = 0; @@ -628,12 +725,12 @@ }; }; 4DDEF3B905474DCC002904DE = { - expectedFileType = archive.ar; isa = PBXFileReference; + lastKnownFileType = archive.ar; name = libxvidcore.a; - path = /usr/local/lib/libxvidcore.a; - refType = 0; - sourceTree = "<absolute>"; + path = ../contrib/libxvidcore/libxvidcore.a; + refType = 2; + sourceTree = SOURCE_ROOT; }; 4DDEF3BA05474DCC002904DE = { fileRef = 4DDEF3B905474DCC002904DE; @@ -642,9 +739,9 @@ }; }; 4DEB2024052B055F00C39CA9 = { - expectedFileType = wrapper.framework; fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; + lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; refType = 0; @@ -657,17 +754,17 @@ }; }; 4DF3C8CB052889CD00A80101 = { - expectedFileType = sourcecode.c.h; fileEncoding = 30; isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; path = Controller.h; refType = 4; sourceTree = "<group>"; }; 4DF3C8CC052889CD00A80101 = { - expectedFileType = sourcecode.cpp.objcpp; fileEncoding = 30; isa = PBXFileReference; + lastKnownFileType = sourcecode.cpp.objcpp; path = Controller.mm; refType = 4; sourceTree = "<group>"; @@ -679,9 +776,9 @@ }; }; 4DFDC318054AC84C00151618 = { - expectedFileType = sourcecode.c.h; fileEncoding = 30; isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; name = HandBrake.h; path = ../core/HandBrake.h; refType = 4; diff --git a/macosx/TargetSizeField.h b/macosx/TargetSizeField.h index 6bc4a716f..d9396ee3a 100644 --- a/macosx/TargetSizeField.h +++ b/macosx/TargetSizeField.h @@ -1,4 +1,4 @@ -/* $Id: TargetSizeField.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ +/* $Id: TargetSizeField.h,v 1.3 2004/01/28 14:41:31 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -12,9 +12,10 @@ { HBTitle * fTitle; - IBOutlet NSTextField * fBitrateField; - IBOutlet NSPopUpButton * fSecondaryLanguagePopUp; - IBOutlet NSPopUpButton * fAudioBitratePopUp; + IBOutlet NSPopUpButton * fRipFormatPopUp; + IBOutlet NSTextField * fRipCustomField; + IBOutlet NSPopUpButton * fRipLang2PopUp; + IBOutlet NSPopUpButton * fRipAudBitPopUp; } - (void) SetHBTitle: (HBTitle *) title; diff --git a/macosx/TargetSizeField.mm b/macosx/TargetSizeField.mm index bde9f0ec2..e113a4bf1 100644 --- a/macosx/TargetSizeField.mm +++ b/macosx/TargetSizeField.mm @@ -1,4 +1,4 @@ -/* $Id: TargetSizeField.mm,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ +/* $Id: TargetSizeField.mm,v 1.4 2004/01/28 14:41:31 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -33,32 +33,16 @@ - (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->length * fTitle->rate / fTitle->rateBase; - - /* Audio tracks */ - available -= ( ( [[fSecondaryLanguagePopUp titleOfSelectedItem] - compare: @"None"] == NSOrderedSame ) ? 1 : 2 ) * - ( fTitle->length * - [[fAudioBitratePopUp titleOfSelectedItem] intValue] * - 128 + 24 * fTitle->length * 44100 / 1152 ); - - if( available < 0 ) - { - [fBitrateField setIntValue: 0]; - } - else - { - [fBitrateField setIntValue: - available / ( 128 * fTitle->length )]; - } + int size = [self intValue]; + int format = [fRipFormatPopUp indexOfSelectedItem]; + int muxer = ( format == 0 ) ? HB_MUX_MP4 : ( ( format == 1 ) ? + HB_MUX_OGM : HB_MUX_AVI ); + int audioCount = ( [fRipLang2PopUp selectedItem] == + [fRipLang2PopUp lastItem] ) ? 1 : 2; + int audioBitrate = [[fRipAudBitPopUp titleOfSelectedItem] intValue]; + + [fRipCustomField setIntValue: HBGetBitrateForSize( fTitle, size, + muxer, audioCount, audioBitrate )]; } @end diff --git a/macosx/genstrings.sh b/macosx/genstrings.sh new file mode 100755 index 000000000..38da1de92 --- /dev/null +++ b/macosx/genstrings.sh @@ -0,0 +1,7 @@ +#! /bin/sh +rm -f genstrings.tmp +cat Controller.mm | grep -v "^#define.*_(" | \ + sed 's/_( \(@"[^"]*"\) )/NSLocalizedString( \1, nil )/g' > \ + genstrings.tmp +genstrings genstrings.tmp +rm -f genstrings.tmp diff --git a/macosx/i18n/French.strings b/macosx/i18n/French.strings Binary files differnew file mode 100644 index 000000000..a81b4ad56 --- /dev/null +++ b/macosx/i18n/French.strings diff --git a/macosx/i18n/German.strings b/macosx/i18n/German.strings Binary files differnew file mode 100644 index 000000000..99220c2cc --- /dev/null +++ b/macosx/i18n/German.strings diff --git a/macosx/i18n/Localizable.strings b/macosx/i18n/Localizable.strings Binary files differnew file mode 100644 index 000000000..cbad7b524 --- /dev/null +++ b/macosx/i18n/Localizable.strings diff --git a/test/test.c b/test/test.c index d59e7ee3e..1a693fde7 100644 --- a/test/test.c +++ b/test/test.c @@ -1,240 +1,516 @@ -/* $Id: test.c,v 1.7 2003/11/13 01:18:52 titer Exp $ +/* $Id: test.c,v 1.26 2004/01/22 19:36:55 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <signal.h> +#include <getopt.h> #include "HandBrake.h" -volatile int die; +/* Options */ +static int verbose = 0; +static char * input = NULL; +static char * output = NULL; +static char * format = NULL; +static int titleindex = 1; +static int twoPass = 0; +static int deinterlace = 0; +static int vcodec = HB_CODEC_FFMPEG; +static char * audios = NULL; +static int width = 0; +static int top = 0; +static int bottom = 0; +static int left = 0; +static int right = 0; +static int autocrop = 0; +static int cpu = 0; +static int vbitrate = 1024; +static int size = 0; +static int abitrate = 128; +static int mux = 0; +static int acodec = 0; + +/* Exit cleanly on Ctrl-C */ +static volatile int die = 0; +static void SigHandler( int ); + +/* Utils */ +static void ShowHelp(); +static int ParseOptions( int argc, char ** argv ); +static int CheckOptions( int argc, char ** argv ); + +/* libhb callbacks */ +static void Scanning( void * data, int title, int titleCount ); +static void ScanDone( void * data, HBList * titleList ); +static void Encoding( void * data, float position, int pass, + int passCount, float frameRate, + float avgFrameRate, int remainingTime ); +static void RipDone( void * data, int result ); -void SigHandler( int signal ) +int main( int argc, char ** argv ) { - die = 1; + HBHandle * h; + HBCallbacks callbacks; + + fprintf( stderr, "HandBrake " HB_VERSION + " - http://handbrake.m0k.org/\n" ); + + if( ParseOptions( argc, argv ) || + CheckOptions( argc, argv ) ) + { + return 1; + } + + /* Exit ASAP on Ctrl-C */ + signal( SIGINT, SigHandler ); + + /* Init libhb */ + h = HBInit( verbose, cpu ); + + /* Set libhb callbacks */ + callbacks.data = h; + callbacks.scanning = Scanning; + callbacks.scanDone = ScanDone; + callbacks.encoding = Encoding; + callbacks.ripDone = RipDone; + HBSetCallbacks( h, callbacks ); + + /* Feed libhb with a DVD to scan */ + fprintf( stderr, "Opening %s...\n", input ); + HBScanDVD( h, input, titleindex ); + + /* Wait... */ + while( !die ) + { + HBSnooze( 500000 ); + } + + /* Clean up */ + HBClose( &h ); + + fprintf( stderr, "HandBrake has exited cleanly.\n" ); + + return 0; } -int main( int argc, char ** argv ) +/**************************************************************************** + * SigHandler: + ****************************************************************************/ +static volatile int64_t i_die_date = 0; +void SigHandler( int i_signal ) { - int c; - HBHandle * h; - HBStatus s; - - /* Default values */ - int debug = 1; - char * device = NULL; - char * file = NULL; - int titleIdx = 1; - int audio1Idx = 1; - int audio2Idx = 0; - int twoPass = 0; - int deinterlace = 0; - int width = 0; - int topCrop = 0; - int bottomCrop = 0; - int leftCrop = 0; - int rightCrop = 0; - int cpuCount = 0; - int vBitrate = 1024; - int aBitrate = 128; - int xvid = 0; - - die = 0; + if( die == 0 ) + { + i_die_date = HBGetDate(); + fprintf( stderr, "Signal %d received, terminating - do it " + "again in case it gets stuck\n", i_signal ); + } + else if( i_die_date + 500000 < HBGetDate() ) + { + fprintf( stderr, "Dying badly, files might remain in your /tmp\n" ); + exit( 1 ); + } + die = 1; +} - /* Exit ASAP on Ctrl-C */ - signal( SIGINT, SigHandler ); +/**************************************************************************** + * ShowHelp: + ****************************************************************************/ +static void ShowHelp() +{ + fprintf( stderr, + "Syntax: HBTest [options] -i <device> -o <file>\n" + "\n" + " -h, --help Print help\n" + " -v, --verbose Be verbose\n" + " -C, --cpu Set CPU count (default: autodetected)\n" + "\n" + " -f, --format <string> Set output format (avi/mp4/ogm, default:\n" + " autodetected)\n" + " -i, --input <string> Set input device\n" + " -o, --output <string> Set output file name\n" + "\n" + " --scan Only scan the device\n" + " -t, --title <number> Select a title to encode (0 to scan only,\n" + " default: 1)\n" + " -a, --audio <string> Select audio channel(s) (none for no audio,\n" + " default: first one)\n" + " --noaudio Disable audio\n" + "\n" + " -c, --codec <string> Set video library encoder (ffmpeg/xvid/x264,\n" + " default: ffmpeg)\n" + " -2, --two-pass Use two-pass mode\n" + " -d, --deinterlace Deinterlace video\n" + "\n" + " -b, --vb <kb/s> Set video bitrate (default: 1024)\n" + " -s, --size <MB> Set target size instead of bitrate\n" + " -B, --ab <kb/s> Set audio bitrate (default: 128)\n" + " -w, --width <number> Set picture width\n" + " --crop <T:B:L:R> Set cropping values\n" + " --autocrop Use autodetected cropping values\n" ); +} - fprintf( stderr, "Welcome to HandBrake " VERSION "\n" ); - /* Parse command line */ - while( ( c = getopt( argc, argv, - "qd:o:t:a:b:piw:j:k:l:m:c:e:f:x" ) ) != -1 ) +/**************************************************************************** + * ParseOptions: + ****************************************************************************/ +static int ParseOptions( int argc, char ** argv ) +{ + for( ;; ) { + static struct option long_options[] = + { + { "help", no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { "cpu", required_argument, NULL, 'C' }, + + { "format", required_argument, NULL, 'f' }, + { "input", required_argument, NULL, 'i' }, + { "output", required_argument, NULL, 'o' }, + + { "scan", no_argument, NULL, 'S' }, + { "title", required_argument, NULL, 't' }, + { "audio", required_argument, NULL, 'a' }, + { "noaudio", no_argument, NULL, 'a' }, + + { "codec", required_argument, NULL, 'c' }, + { "two-pass", no_argument, NULL, '2' }, + { "deinterlace", no_argument, NULL, 'd' }, + { "width", required_argument, NULL, 'w' }, + { "crop", required_argument, NULL, 'n' }, + { "autocrop", no_argument, NULL, 'z' }, + + { "vb", required_argument, NULL, 'b' }, + { "size", required_argument, NULL, 's' }, + { "ab", required_argument, NULL, 'B' }, + + { 0, 0, 0, 0 } + }; + + int option_index = 0; + int c; + + c = getopt_long( argc, argv, "hvC:f:i:o:St:a:c:2dw:n:zb:s:B:", + long_options, &option_index ); + if( c < 0 ) + { + break; + } + switch( c ) { - case 'q': - debug = 0; + case 'h': + ShowHelp(); + exit( 0 ); + case 'v': + verbose = 1; break; - - case 'd': - device = strdup( optarg ); + case 'C': + cpu = atoi( optarg ); break; + case 'f': + format = strdup( optarg ); + break; + case 'i': + input = strdup( optarg ); + break; case 'o': - file = strdup( optarg ); + output = strdup( optarg ); break; + case 'S': + titleindex = 0; + break; case 't': - titleIdx = atoi( optarg ); + titleindex = atoi( optarg ); break; - case 'a': - audio1Idx = atoi( optarg ); + audios = strdup( optarg ? optarg : "none" ); break; - case 'b': - audio2Idx = atoi( optarg ); - break; - - case 'p': + case '2': twoPass = 1; break; - - case 'i': + case 'd': deinterlace = 1; break; - + case 'c': + if( !strcasecmp( optarg, "ffmpeg" ) ) + { + vcodec = HB_CODEC_FFMPEG; + } + else if( !strcasecmp( optarg, "xvid" ) ) + { + vcodec = HB_CODEC_XVID; + } + else if( !strcasecmp( optarg, "x264" ) ) + { + vcodec = HB_CODEC_X264; + } + else + { + fprintf( stderr, "invalid codec (%s)\n", optarg ); + return -1; + } + break; case 'w': width = atoi( optarg ); break; - - case 'j': - topCrop = atoi( optarg ); - break; - - case 'k': - bottomCrop = atoi( optarg ); - break; - - case 'l': - leftCrop = atoi( optarg ); - break; - - case 'm': - rightCrop = atoi( optarg ); + case 'n': + { + char * crop = strdup( optarg ); + char * _2be3 = crop; + + if( *crop ) + { + top = strtol( crop, &crop, 0 ); crop++; + } + if( *crop ) + { + bottom = strtol( crop, &crop, 0 ); crop++; + } + if( *crop ) + { + left = strtol( crop, &crop, 0 ); crop++; + } + if( *crop ) + { + right = strtol( crop, &crop, 0 ); crop++; + } + + free( _2be3 ); break; + } + case 'z': + autocrop = 1; + break; - case 'c': - cpuCount = atoi( optarg ); + case 'b': + vbitrate = atoi( optarg ); break; - - case 'e': - vBitrate = atoi( optarg ); + case 's': + size = atoi( optarg ); break; - - case 'f': - aBitrate = atoi( optarg ); - break; - - case 'x': - xvid = 1; + case 'B': + abitrate = atoi( optarg ); break; default: - break; + fprintf( stderr, "unknown option (%s)\n", argv[optind] ); + return -1; } } - /* Check parsed options */ - if( !device || !file ) - { - fprintf( stderr, - "Syntax: HBTest [options] -d <device> -o <file>\n" - "Possible options are :\n" - " -q quiet 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 (default: autodetected)\n" - " -e <value> Video bitrate (default is 1024)\n" - " -f <value> Audio bitrate (default is 128)\n" - " -x Use XviD instead of Ffmpeg\n" ); + return 0; +} + +static int CheckOptions( int argc, char ** argv ) +{ + if( input == NULL || *input == '\0' ) + { + fprintf( stderr, "Missing input device. Run %s --help for " + "syntax.\n", argv[0] ); return 1; } - /* Create the lihb thread & init things */ - h = HBInit( debug, cpuCount ); - - while( !die ) + /* Parse format */ + if( titleindex > 0 ) { - HBSnooze( 100000 ); + if( output == NULL || *output == '\0' ) + { + fprintf( stderr, "Missing output file name. Run %s --help " + "for syntax.\n", argv[0] ); + return 1; + } - if( !HBGetStatus( h, &s ) ) - continue; + if( !format ) + { + char *p = strrchr( output, '.' ); + /* autodetect */ + if( p && !strcasecmp( p, ".avi" ) ) + { + mux = HB_MUX_AVI; + } + else if( p && !strcasecmp( p, ".mp4" ) ) + { + mux = HB_MUX_MP4; + } + else if( p && ( !strcasecmp( p, ".ogm" ) || + !strcasecmp( p, ".ogg" ) ) ) + { + mux = HB_MUX_OGM; + } - switch( s.mode ) + else + { + fprintf( stderr, "Output format couldn't be guessed " + "from file name, please use --format.\n" ); + return 1; + } + } + else if( !strcasecmp( format, "avi" ) ) { - case HB_MODE_UNDEF: - /* Will never happen */ - break; + mux = HB_MUX_AVI; + } + else if( !strcasecmp( format, "mp4" ) ) + { + mux = HB_MUX_MP4; + } + else if( !strcasecmp( format, "ogm" ) || + !strcasecmp( format, "ogg" ) ) + { + mux = HB_MUX_OGM; + } + else + { + fprintf( stderr, "Invalid output format (%s). Possible " + "choices are avi, mp4 and ogm\n.", format ); + return 1; + } + if( mux == HB_MUX_MP4 ) + { + acodec = HB_CODEC_AAC; + } + else if( mux == HB_MUX_AVI ) + { + acodec = HB_CODEC_MP3; + } + else if( mux == HB_MUX_OGM ) + { + acodec = HB_CODEC_VORBIS; + } + } - case HB_MODE_NEED_DEVICE: - /* Feed libhb with a DVD to scan */ - HBScanDevice( h, device, titleIdx ); - break; + return 0; +} - case HB_MODE_SCANNING: - /* s.scannedTitle: title scanned at the moment */ - break; +static void Scanning( void * data, int title, int titleCount ) +{ + if( titleindex ) + { + fprintf( stderr, "Scanning title %d...\n", title ); + } + else + { + fprintf( stderr, "Scanning title %d/%d...\n", title, titleCount ); + } +} - case HB_MODE_INVALID_DEVICE: - die = 1; - break; +static void ScanDone( void * data, HBList * titleList ) +{ + HBHandle * h = (HBHandle*) data; + HBAudio * audio; + HBTitle * title; - case HB_MODE_READY_TO_RIP: - { - HBAudio * audio1, * audio2; - HBTitle * title = HBListItemAt( s.titleList, 0 ); - - title->file = strdup( file ); - title->twoPass = twoPass; - title->deinterlace = deinterlace; - if( width ) title->outWidth = width; - title->topCrop = topCrop; - title->bottomCrop = bottomCrop; - title->leftCrop = leftCrop; - title->rightCrop = rightCrop; - title->bitrate = vBitrate; - title->codec = xvid ? HB_CODEC_XVID : HB_CODEC_FFMPEG; - - audio1 = HBListItemAt( title->audioList, - audio1Idx - 1 ); - audio2 = HBListItemAt( title->audioList, - audio2Idx - 1 ); - if( audio1 ) audio1->outBitrate = aBitrate; - if( audio2 ) audio2->outBitrate = aBitrate; - - HBStartRip( h, title, audio1, audio2 ); - break; - } + if( !titleList ) + { + fprintf( stderr, "No title found. Invalid device?\n" ); + die = 1; + return; + } + if( !titleindex ) + { + die = 1; + return; + } - case HB_MODE_ENCODING: - /* s.position : current progress (0.0->1.0) - s.frameRate : average framerate - s.remainingTime: ... (in seconds) */ - break; + title = HBListItemAt( titleList, 0 ); + title->file = strdup( output ); + title->twoPass = twoPass; + title->deinterlace = deinterlace; + if( width ) + { + title->outWidth = width; + } + if( autocrop ) + { + title->topCrop = title->autoTopCrop; + title->bottomCrop = title->autoBottomCrop; + title->leftCrop = title->autoLeftCrop; + title->rightCrop = title->autoRightCrop; + } + else + { + title->topCrop = top; + title->bottomCrop = bottom; + title->leftCrop = left; + title->rightCrop = right; + } + fprintf( stderr, "Cropping: T=%d,B=%d,L=%d,R=%d\n", + title->topCrop, title->bottomCrop, + title->leftCrop, title->rightCrop ); + title->bitrate = vbitrate; + title->codec = vcodec; + title->mux = mux; + + if( audios == NULL ) + { + audio = HBListItemAt( title->audioList, 0 ); + audio->outBitrate = abitrate; + audio->codec = acodec; + HBListAdd( title->ripAudioList, audio ); + } + else if( strcasecmp( audios, "none" ) ) + { + char *tmp = audios; - case HB_MODE_DONE: - die = 1; - break; + while( *tmp ) + { + int i; - case HB_MODE_CANCELED: - die = 1; - break; + if( *tmp < '0' || *tmp > '9' ) + { + /* Skip non numeric char */ + tmp++; + continue; + } - case HB_MODE_ERROR: - /* s.error: error code */ - die = 1; - break; + i = strtol( tmp, &tmp, 0 ); + audio = HBListItemAt( title->audioList, i - 1 ); + audio->outBitrate = abitrate; + audio->codec = acodec; + HBListAdd( title->ripAudioList, audio ); - default: - break; + tmp++; } } + if( size ) + { + title->bitrate = HBGetBitrateForSize( title, size, title->mux, + HBListCount( title->ripAudioList ), abitrate ); + fprintf( stderr, "Calculated bitrate: %d kbps\n", title->bitrate ); + } - HBClose( &h ); + HBStartRip( h, title ); +} - if( device ) free( device ); - if( file ) free( file ); +static void Encoding( void * data, float position, int pass, + int passCount, float frameRate, + float avgFrameRate, int remainingTime ) +{ + fprintf( stderr, "%6.2f %% (pass: %d/%d, cur/avg speed: " + "%5.2f/%5.2f fps, %02d:%02d:%02d remaining)\n", + 100.0 * position, pass, passCount, frameRate, avgFrameRate, + remainingTime / 3600, ( remainingTime / 60 ) % 60, + remainingTime % 60 ); +} - return 0; +static void RipDone( void * data, int result ) +{ + switch( result ) + { + case HB_SUCCESS: + fprintf( stderr, "Rip done!\n" ); + break; + case HB_CANCELED: + fprintf( stderr, "Rip canceled.\n" ); + break; + default: + fprintf( stderr, "Rip failed (error %x).\n", result ); + } + die = 1; } |