summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS18
-rw-r--r--BUILD30
-rw-r--r--CREDITS35
-rw-r--r--Jamfile135
-rw-r--r--Jamrules126
-rw-r--r--NEWS58
-rw-r--r--TODO33
-rw-r--r--beos/HBApp.cpp34
-rw-r--r--beos/HBApp.h22
-rw-r--r--beos/HBWindow.cpp283
-rw-r--r--beos/HBWindow.h41
-rw-r--r--beos/MainWindow.cpp165
-rw-r--r--beos/MainWindow.h36
-rw-r--r--beos/PictureWin.cpp232
-rw-r--r--beos/PictureWin.h52
-rw-r--r--beos/RipView.cpp638
-rw-r--r--beos/RipView.h77
-rw-r--r--beos/ScanView.cpp286
-rw-r--r--beos/ScanView.h48
-rw-r--r--beos/liblayout/HGroup.h40
-rw-r--r--beos/liblayout/LayeredGroup.h37
-rw-r--r--beos/liblayout/MApplication.h29
-rw-r--r--beos/liblayout/MBViewWrapper.h30
-rw-r--r--beos/liblayout/MBorder.h68
-rw-r--r--beos/liblayout/MButton.h53
-rw-r--r--beos/liblayout/MCheckBox.h33
-rw-r--r--beos/liblayout/MDividable.h35
-rw-r--r--beos/liblayout/MDragBar.h38
-rw-r--r--beos/liblayout/MEject.h23
-rw-r--r--beos/liblayout/MFFWD.h24
-rw-r--r--beos/liblayout/MGroup.h31
-rw-r--r--beos/liblayout/MListView.h30
-rw-r--r--beos/liblayout/MMenuBar.h33
-rw-r--r--beos/liblayout/MOutlineListView.h32
-rw-r--r--beos/liblayout/MPictureButton.h55
-rw-r--r--beos/liblayout/MPlayBW.h23
-rw-r--r--beos/liblayout/MPlayFW.h22
-rw-r--r--beos/liblayout/MPopup.h45
-rw-r--r--beos/liblayout/MProgressBar.h58
-rw-r--r--beos/liblayout/MRadioGroup.h46
-rw-r--r--beos/liblayout/MRew.h22
-rw-r--r--beos/liblayout/MScrollView.h39
-rw-r--r--beos/liblayout/MSlider.h30
-rw-r--r--beos/liblayout/MSplitter.h38
-rw-r--r--beos/liblayout/MStop.h22
-rw-r--r--beos/liblayout/MStringView.h25
-rw-r--r--beos/liblayout/MTabView.h33
-rw-r--r--beos/liblayout/MTextControl.h36
-rw-r--r--beos/liblayout/MTextView.h31
-rw-r--r--beos/liblayout/MVolume.h48
-rw-r--r--beos/liblayout/MWindow.h62
-rw-r--r--beos/liblayout/PropGadget.h75
-rw-r--r--beos/liblayout/Space.h22
-rw-r--r--beos/liblayout/SpinButton.h78
-rw-r--r--beos/liblayout/TabGroup.h46
-rw-r--r--beos/liblayout/VGroup.h41
-rw-r--r--beos/liblayout/layout-all.h35
-rw-r--r--beos/liblayout/layout.h168
-rw-r--r--core/Ac3Dec.c68
-rw-r--r--core/Ac3Dec.h15
-rw-r--r--core/AviMux.c425
-rw-r--r--core/AviMux.h15
-rw-r--r--core/DVDRead.c214
-rw-r--r--core/DVDRead.h16
-rw-r--r--core/FaacEnc.c214
-rw-r--r--core/FfmpegEnc.c293
-rw-r--r--core/FfmpegEnc.h15
-rw-r--r--core/Fifo.c24
-rw-r--r--core/Fifo.h85
-rw-r--r--core/HBInternal.h81
-rw-r--r--core/HandBrake.c599
-rw-r--r--core/HandBrake.h50
-rw-r--r--core/HandBrakeInternal.h35
-rw-r--r--core/Jamfile47
-rw-r--r--core/MadDec.c5
-rw-r--r--core/MadDec.h15
-rw-r--r--core/Mp3Enc.c118
-rw-r--r--core/Mp3Enc.h15
-rw-r--r--core/Mp4Mux.c210
-rw-r--r--core/Mpeg2Dec.c62
-rw-r--r--core/Mpeg2Dec.h15
-rw-r--r--core/OgmMux.c471
-rw-r--r--core/Scale.c73
-rw-r--r--core/Scale.h15
-rw-r--r--core/Scan.c254
-rw-r--r--core/Scan.h15
-rw-r--r--core/Thread.c77
-rw-r--r--core/Thread.h105
-rw-r--r--core/Utils.c94
-rw-r--r--core/Utils.h260
-rw-r--r--core/VorbisEnc.c257
-rw-r--r--core/Work.c120
-rw-r--r--core/Work.h12
-rw-r--r--core/X264Enc.c167
-rw-r--r--core/XvidEnc.c227
-rw-r--r--core/XvidEnc.h15
-rw-r--r--core/XvidVbr.c1648
-rw-r--r--core/XvidVbr.h231
-rw-r--r--gtk2/callbacks.c623
-rw-r--r--gtk2/callbacks.h75
-rw-r--r--gtk2/gtk2hb.glade1863
-rw-r--r--gtk2/interface.c984
-rw-r--r--gtk2/interface.h7
-rw-r--r--gtk2/main.c409
-rw-r--r--gtk2/status.h33
-rw-r--r--gtk2/support.c144
-rw-r--r--gtk2/support.h44
-rw-r--r--macosx/Controller.h112
-rw-r--r--macosx/Controller.mm950
-rw-r--r--macosx/English.lproj/InfoPlist.stringsbin496 -> 500 bytes
-rw-r--r--macosx/English.lproj/MainMenu.nib/classes.nib94
-rw-r--r--macosx/English.lproj/MainMenu.nib/info.nib22
-rw-r--r--macosx/English.lproj/MainMenu.nib/objects.nibbin18081 -> 19591 bytes
-rw-r--r--macosx/HandBrake.xcode/project.pbxproj (renamed from macosx/HandBrake.pbproj/project.pbxproj)219
-rw-r--r--macosx/TargetSizeField.h9
-rw-r--r--macosx/TargetSizeField.mm38
-rwxr-xr-xmacosx/genstrings.sh7
-rw-r--r--macosx/i18n/French.stringsbin0 -> 10044 bytes
-rw-r--r--macosx/i18n/German.stringsbin0 -> 4318 bytes
-rw-r--r--macosx/i18n/Localizable.stringsbin0 -> 9912 bytes
-rw-r--r--test/test.c614
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
+
diff --git a/BUILD b/BUILD
new file mode 100644
index 000000000..40da5e7ec
--- /dev/null
+++ b/BUILD
@@ -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.
+
diff --git a/CREDITS b/CREDITS
index 4000b2ddc..75bc7b32f 100644
--- a/CREDITS
+++ b/CREDITS
@@ -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
diff --git a/Jamfile b/Jamfile
index a96bf5942..603ef155a 100644
--- a/Jamfile
+++ b/Jamfile
@@ -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)"
+}
+
diff --git a/NEWS b/NEWS
index 9abb4a2d7..b198d096d 100644
--- a/NEWS
+++ b/NEWS
@@ -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.
diff --git a/TODO b/TODO
index 970849099..8248abac5 100644
--- a/TODO
+++ b/TODO
@@ -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( &param, 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( &param );
+
+ 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( &param ) ) == 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 &amp; 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
index ce3b28a62..714d974fa 100644
--- a/macosx/English.lproj/InfoPlist.strings
+++ b/macosx/English.lproj/InfoPlist.strings
Binary files differ
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
index 956897bce..b088624ed 100644
--- a/macosx/English.lproj/MainMenu.nib/objects.nib
+++ b/macosx/English.lproj/MainMenu.nib/objects.nib
Binary files differ
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 &lt;[email protected]&gt;</string>
+ <string>HandBrake 0.5.2+ - By Eric Petit &lt;[email protected]&gt;</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
new file mode 100644
index 000000000..a81b4ad56
--- /dev/null
+++ b/macosx/i18n/French.strings
Binary files differ
diff --git a/macosx/i18n/German.strings b/macosx/i18n/German.strings
new file mode 100644
index 000000000..99220c2cc
--- /dev/null
+++ b/macosx/i18n/German.strings
Binary files differ
diff --git a/macosx/i18n/Localizable.strings b/macosx/i18n/Localizable.strings
new file mode 100644
index 000000000..cbad7b524
--- /dev/null
+++ b/macosx/i18n/Localizable.strings
Binary files differ
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;
}