1#!/usr/bin/perl -w
2
3package acidrip;
4require 5.000;
5use strict;
6use POSIX;    #needed for floor()
7use AcidRip::interface;
8use AcidRip::signals;
9use AcidRip::messages;
10use Data::Dumper;
11use File::Basename;
12use Gtk2::Helper;
13
14sub gui_check ($) {
15  if (/SKIN/) {
16    my $msg = "You have set gui=yes in your config file. this is not a valid MPlayer option, only there for debugging. Remove it and use gmplayer instead for a gui!";
17    message($msg);
18    print $msg . "\n";
19  }
20}
21
22sub set_warning_text ($$) {
23  my $widget = shift;
24  my $warn   = shift;
25  $widget->modify_text( 'normal', Gtk2::Gdk::Color->new( $warn * 65535, 0, 0 ) );
26}
27
28sub hhmmss ($) {
29  my $s    = shift;
30  my $m    = floor $s / 60;
31  my $mins = $m % 60;
32  my $hour = floor $m / 60;
33  return sprintf( "%d:%02d:%02d", $hour, $mins, $s % 60 );
34}
35
36sub split_track {
37  if ( defined $::dvd->{'track'} && defined get_track()->{'chapter'}) {
38    $::settings->{'blocks'} = undef;
39    $::settings->{'blocks'} = ();
40    my $start = $::settings->{'selected_chapters_start'} || 1;
41    my $stop  = $::settings->{'selected_chapters_end'}   || get_track()->{'chapter'}[-1]->{'ix'};
42    my $total_length = get_selection_length();
43
44    my $length     = 0;
45    my $this_block = 1;
46    my $old_length = $length;
47    $::settings->{'blocks'}[0] = $start - 1;
48
49    foreach my $chapter ( $start .. $stop ) {
50      my $this_chapter = get_chapter($chapter);
51      my $target       = $total_length * $this_block / $::settings->{'total_blocks'};
52      $length += $this_chapter->{'length'};
53      $::settings->{'blocks'}[$this_block] = $chapter;
54      $this_block++ if $old_length < $target && $length > $target;
55      $old_length = $length;
56    }
57
58    $::settings->{'UI'} && set_warning_text( $::widgets->{'total_blocks_spin'}, ( scalar @{ $::settings->{'blocks'} } ) - 1 < $::settings->{'total_blocks'} ? 1 : 0 );
59    my $msg = "Blocks: ";
60    for ( 1 .. @{ $::settings->{'blocks'} } - 1 ) {
61      $msg .= " $_=[" . ( $::settings->{'blocks'}[ $_ - 1 ] + 1 ) . "-" . ( $::settings->{'blocks'}[$_] ) . "] ";
62    }
63    message($msg);
64    return @{ $::settings->{'blocks'} };
65  }
66	elsif ( defined $::dvd->{'track'}) {
67		message("Can't split video files, only DVD's") if $::dvd->{'source'} eq 'file';
68		message("Can't split track - No chapters on this DVD track") if $::dvd->{'source'} eq "dvd";
69	}
70  else {
71    message("Can't split track - No DVD loaded!");
72  }
73}
74
75sub converttoint {
76  my $total = 0;
77  my $i;
78  my $data = shift;
79  for ( $i = 0 ; $i < length($data) ; $i++ ) {
80    my $c = substr( $data, $i, 1 );
81    my $value = 256**$i * ord($c);
82    $total += $value;
83  }
84  return $total;
85}
86
87sub get_track {
88  my $ix = shift || $::settings->{'selected_track'};
89  return -1 if ! defined $::dvd->{'track'};
90  return -1 if ! scalar @{$::dvd->{'track'}};
91
92  foreach ( @{ $::dvd->{'track'} } ) {
93    return $_ if $ix == $_->{'ix'};
94  }
95  return -1;
96}
97
98sub get_track_param ($) {
99	my $param = shift;
100	my $track = get_track();
101	if (ref($track) eq 'HASH' and defined $track->{$param}) {
102		return $track->{$param}
103	} else {
104		return -1
105	}
106}
107
108sub get_audio {
109  my $ix = shift;
110  my $track = get_track( shift || $::settings->{'selected_track'} );
111  foreach ( @{ $track->{'audio'} } ) {
112    return $_ if $ix == $_->{'ix'};
113  }
114  return -1;
115}
116
117sub get_chapter {
118  my $ix = shift;
119  my $track = get_track( shift || $::settings->{'selected_track'} );
120  foreach ( @{ $track->{'chapter'} } ) {
121    return $_ if $ix == $_->{'ix'};
122  }
123  return -1;
124}
125
126sub get_cell {
127  my $ix = shift;
128  my $track = get_track( shift || $::settings->{'selected_track'} );
129  foreach ( @{ $track->{'cell'} } ) {
130    return $_ if $ix == $_->{'ix'};
131  }
132  return -1;
133}
134
135sub message {
136  my ( $data, $tag ) = @_;
137
138  if ( defined $::widgets ) {
139    my $context_id = $::widgets->{'status_bar'}->get_context_id('acidrip');
140    $::widgets->{'status_bar'}->pop($context_id);
141    $::widgets->{'status_bar'}->push( $context_id, $data );
142    my $iter = $::widgets->{'mencoder_output_text'}->get_buffer->get_end_iter;
143    if ($tag) {
144      $::widgets->{'mencoder_output_text'}->get_buffer->insert_with_tags_by_name( $iter, "AcidRip message - $data\n", $tag );
145    }
146    else {
147      $::widgets->{'mencoder_output_text'}->get_buffer->insert( $iter, "AcidRip message - $data\n" );
148    }
149  }
150  else {
151    print "AcidRip message - $data\n";
152  }
153}
154
155sub load_settings_to_interface {
156  foreach my $value ( keys %{$::settings} ) {
157    $::widgets->{ $value . "_entry" }->set_text( $::settings->{$value} )
158      if defined( $::widgets->{ $value . "_entry" } )
159      and $value ne $::widgets->{ $value . "_entry" }->get_text;
160    $::widgets->{ $value . "_spin" }->set_value( $::settings->{$value} )
161      if defined( $::widgets->{ $value . "_spin" } )
162      and $value ne $::widgets->{ $value . "_spin" }->get_value_as_int;
163    $::widgets->{ $value . "_check" }->set_active( $::settings->{$value} )
164      if defined( $::widgets->{ $value . "_check" } );
165    $::widgets->{ $value . "_option" }->set_history( $::settings->{$value} )
166      if ( $::settings->{$value} =~ /^\d+$/ )
167      and defined( $::widgets->{ $value . "_option" } );
168  }
169}
170
171sub set_setting ($$) {
172  my ( $name, $data ) = @_;
173  $::settings->{$name} = $data;
174  $::widgets->{ $name . "_entry" }->set_text($data)
175    if defined $::widgets->{ $name . "_entry" } and $data ne $::widgets->{ $name . "_entry" }->get_text;    # and $::widgets->{$name . "_entry"}->get('editable');
176  $::widgets->{ $name . "_spin" }->set_value($data)
177    if defined $::widgets->{ $name . "_spin" } and $data ne $::widgets->{ $name . "_spin" }->get_value;     #and $::widgets->{$name . "_spin"}->get('editable');
178}
179
180sub substitute_filename ($) {
181  my $filename = shift;
182  my $f = substr( $::settings->{'title'}, 0, 1 );
183  $filename =~ s/%N/$::settings->{'selected_track'}/g;                                                      # track Number
184  $filename =~ s/%f/$f/g;                                                                                   # First letter of title
185  $filename =~ s/%T/$::settings->{'title'}/g;                                                               # Title
186  $filename =~ s/%L/$::settings->{'length'}/g;                                                              # Length
187  $filename =~ s/%b/$::settings->{'video_bitrate'}/g;                                                       # bitrate
188  $filename =~ s/%l/$::settings->{'language'}/g;                                                            # language
189  $filename =~ s/%w/$::settings->{'scale_width'}/g;                                                         # width
190  $filename =~ s/%h/$::settings->{'scale_height'}/g;                                                        # height
191  return $filename;
192}
193
194sub get_parameters {
195  split_track() if $::settings->{'total_blocks'} > 1;
196  set_bitrate() if $::settings->{'this_block'} > 0;
197
198  my %menc   = ();
199  my $length = get_track()->{'length'};
200
201  $menc{'video_options'} = $::settings->{'video_options'};
202  $menc{'video'}         = "-ovc $::settings->{'video_codec'}";
203
204  $menc{'info'} = "-info srcform=\"DVD ripped by acidrip.sf.net\"";
205  $menc{'info'} .= ":name=\"$::settings->{'info_name'}\""           if defined $::settings->{'info_name'}      && $::settings->{'info_name'}      ne '';
206  $menc{'info'} .= ":comment=\"$::settings->{'info_comment'}\""     if defined $::settings->{'info_comment'}   && $::settings->{'info_comment'}   ne '';
207  $menc{'info'} .= ":artist=\"$::settings->{'info_artist'}\""       if defined $::settings->{'info_artist'}    && $::settings->{'info_artist'}    ne '';
208  $menc{'info'} .= ":subject=\"$::settings->{'info_subject'}\""     if defined $::settings->{'info_subject'}   && $::settings->{'info_subject'}   ne '';
209  $menc{'info'} .= ":genre=\"$::settings->{'info_genre'}\""         if defined $::settings->{'info_genre'}     && $::settings->{'info_genre'}     ne '';
210  $menc{'info'} .= ":copyright=\"$::settings->{'info_copyright'}\"" if defined $::settings->{'info_copyright'} && $::settings->{'info_copyright'} ne '';
211
212  if ( $::settings->{'video_codec'} eq 'lavc' ) {
213    $menc{'video'} = "-ovc lavc -lavcopts $::settings->{'lavc_options'}:vbitrate=$::settings->{'video_bitrate'}";
214    $menc{'video'} .= ":vpass=$::settings->{'video_pass'}" if $::settings->{'video_passes'} > 1;
215  }
216  if ( $::settings->{'video_codec'} eq 'divx4' ) {
217    $menc{'video'} = "-ovc divx4 -divx4opts $::settings->{'divx4_options'}:br=$::settings->{'video_bitrate'}";
218    $menc{'video'} .= ":pass=$::settings->{'video_pass'}" if $::settings->{'video_passes'} > 1;
219  }
220  if ( $::settings->{'video_codec'} eq 'xvid' ) {
221#----------------
222#ORIGINAL    $menc{'video'} = "-ovc xvid -xvidencopts $::settings->{'xvid_options'}:bitrate=$::settings->{'video_bitrate'}";
223             $menc{'video'} = "-ovc xvid -xvidencopts ";
224		if ( $::settings->{'xvid_options'} eq '' )
225			{
226    			# my $msgaa = "AA You have no xvid_options set.";
227    			# message($msgaa);
228    			# print $msgaa . "\n";
229    			# my $msgbb = "BB You have no xvid_options set.";
230    			# message($msgbb);
231    			# print $msgbb . "\n";
232			}
233		else
234			{
235    			# my $msgaa = "AA You do have some xvid_options set.";
236    			# message($msgaa);
237    			# print $msgaa . "\n";
238    			# my $msgbb = "BB You do have some xvid_options set.";
239    			# message($msgbb);
240    			# print $msgbb . "\n";
241	     		$menc{'video'} .= "$::settings->{'xvid_options'}:" ;
242			}
243	     $menc{'video'} .= "bitrate=$::settings->{'video_bitrate'}";
244    $menc{'video'} .= ":pass=$::settings->{'video_pass'}" if $::settings->{'video_passes'} > 1;
245  }
246  if ( $::settings->{'video_codec'} eq 'nuv' ) {
247    $menc{'video'} = "-ovc nuv -nuvopts $::settings->{'nuv_options'}";
248  }
249
250  if ( $::dvd->{'source'} eq "dvd" ) {
251    $menc{'dvdplay'} = "dvd://$::settings->{'selected_track'}";
252    $menc{'dvdplay'} .= " -dvd-device $::settings->{'dvd_device'}" if $::settings->{'dvd_device'} ne '';
253    $menc{'dvdmenc'} = $menc{'dvdplay'};
254
255    if ( $::settings->{'mplayer_version'} < 1 ) {
256      $menc{'dvdmenc'} = "-dvd $::settings->{'selected_track'}";
257      $menc{'dvdmenc'} .= " -dvd-device $::settings->{'dvd_device'}" if $::settings->{'dvd_device'} ne '';
258    }
259    if ( $::settings->{'mplayer_version'} < 0.9 ) {
260      $menc{'dvdplay'} = "-dvd $::settings->{'selected_track'}";
261      $menc{'dvdplay'} .= " -dvd-device $::settings->{'dvd_device'}" if $::settings->{'dvd_device'} ne '';
262    }
263  }
264  else {
265    $menc{'dvdplay'} = quotemeta( get_track()->{'filename'} );
266    $menc{'dvdmenc'} = quotemeta( get_track()->{'filename'} );
267  }
268
269  $menc{'audio_track'} = '';
270  $menc{'audio_track'} = "-alang $::settings->{'language'}" if ( $::settings->{'selected_audio'} == -1 );
271  $menc{'audio_track'} = "-nosound" if ( $::settings->{'selected_audio'} == -2 );
272  $menc{'audio_track'} = join( " ", "-aid", $::settings->{'selected_audio'} + 127 ) if ( $::settings->{'selected_audio'} > 0 );
273
274  $menc{'audio'} = "-oac $::settings->{'audio_codec'}";
275  $menc{'audio'} .= " -lameopts $::settings->{'audio_mp3lame_options'}" if $::settings->{'audio_codec'} eq 'mp3lame';
276  $menc{'audio'} .= " -lavcopts $::settings->{'audio_lavc_options'}"    if $::settings->{'audio_codec'} eq 'lavc';
277	$menc{'audio'} = '' if ( $::settings->{'selected_audio'} == -2 );
278
279  $menc{'basename'} = substitute_filename( $::settings->{'filename'} );
280  $menc{'basename'} = $menc{'basename'} . "-" . $::settings->{'this_block'} if $::settings->{'this_block'};
281
282  $menc{'output'} = $::settings->{'video_pass'} == 1 ? "/dev/null" : $menc{'basename'} . ( $::settings->{'mpegfile'} ? ".mpg" : ".avi" );
283
284  $menc{'af'} = $::settings->{'audio_gain'} == 0 ? "" : "-af volume=" . $::settings->{'audio_gain'} . ":sc";
285  $menc{'af'} = '' if ( $::settings->{'selected_audio'} == -2 );
286
287  $menc{'mpegfile'} = $::settings->{'mpegfile'} ? "-of mpeg" : "";
288
289  $menc{'subp'} = $::settings->{'selected_subp'} > -1 ? "-sid " . ( $::settings->{'selected_subp'} - 1 ) : "";
290
291  $menc{'subout'} = $::settings->{'vobsubout'} ? "-vobsubout $menc{'basename'}" : "";
292
293  $menc{'scale'} = $::settings->{'scale_enable'} ? "scale=$::settings->{'scale_width'}:$::settings->{'scale_height'}" : "";
294
295  $menc{'crop'} =
296    $::settings->{'crop_enable'} ? "crop=$::settings->{'crop_width'}:$::settings->{'crop_height'}:$::settings->{'crop_horizontal'}:$::settings->{'crop_vertical'}" : '';
297
298  $menc{'vf'} = ( $::settings->{'mplayer_version'} < 1 ) ? "-vop" : "-vf";
299
300  $menc{'vf_pre'} = $::settings->{'vf_pre'} if $::settings->{'vf_pre_enable'} && $::settings->{'vf_pre'} ne '';
301
302  $menc{'vf_post'} = $::settings->{'vf_post'} if $::settings->{'vf_post_enable'} && $::settings->{'vf_post'} ne '';
303
304  my $cw = $::settings->{'crop_width'}  || get_track()->{'width'};
305  my $ch = $::settings->{'crop_height'} || get_track()->{'height'};
306
307  my @vfoptions;
308  if ( $::settings->{'mplayer_version'} < 1 ) {
309    push( @vfoptions, $menc{'vf_post'} ) if $menc{'vf_post'};
310    push( @vfoptions, $menc{'scale'} )   if $menc{'scale'};
311    push( @vfoptions, $menc{'crop'} )    if $menc{'crop'};
312    push( @vfoptions, $menc{'vf_pre'} )  if $menc{'vf_pre'};
313
314    $menc{'embed'} =
315      $::settings->{'embed_preview'}
316      ? " -vop scale=" . $::widgets->{'preview_socket'}->allocation->width . ":-2,$menc{'crop'} -wid " . $::widgets->{'preview_socket'}->get_id
317      : ( @vfoptions ? "$menc{'vf'} " . join( ",", @vfoptions ) : '' );
318  }
319  else {
320    push( @vfoptions, $menc{'vf_pre'} )  if $menc{'vf_pre'};
321    push( @vfoptions, $menc{'crop'} )    if $menc{'crop'};
322    push( @vfoptions, $menc{'scale'} )   if $menc{'scale'};
323    push( @vfoptions, $menc{'vf_post'} ) if $menc{'vf_post'};
324
325    $menc{'crop'} .= "," if $menc{'crop'};
326
327    $menc{'embed'} =
328      $::settings->{'embed_preview'}
329      ? " -vf $menc{'crop'}scale=" . $::widgets->{'preview_socket'}->allocation->width . ":-2 -wid " . $::widgets->{'preview_socket'}->get_id
330      : ( @vfoptions ? "$menc{'vf'} " . join( ",", @vfoptions ) : '' );
331  }
332
333  $menc{'vf_filters'} = ($::settings->{'video_codec'} ne 'copy' && scalar(@vfoptions)) ? "$menc{'vf'} " . join( ",", @vfoptions ) : "";
334
335  $menc{'chapter'} = '';
336  if ( $::settings->{'total_blocks'} > 1 && $::settings->{'this_block'} > 0 && $::dvd->{'source'} eq "dvd") {
337    $menc{'chapter'} = "-chapter " . ( $::settings->{'blocks'}[ $::settings->{'this_block'} - 1 ] + 1 ) . "-" . $::settings->{'blocks'}[ $::settings->{'this_block'} ];
338    $length = get_selection_length( $::settings->{'blocks'}[ $::settings->{'this_block'} - 1 ] + 1, $::settings->{'blocks'}[ $::settings->{'this_block'} ] );
339  }
340  elsif ( $::settings->{'selected_chapters_start'} > 0 && $::settings->{'selected_chapters_end'} > 0 && $::dvd->{'source'} eq "dvd") {
341    $menc{'chapter'} = "-chapter $::settings->{'selected_chapters_start'}-$::settings->{'selected_chapters_end'}";
342    $length = get_selection_length( $::settings->{'selected_chapters_start'}, $::settings->{'selected_chapters_end'} );
343  }
344
345  my $frames = $::settings->{'ppc_bug'} ? 100 : 10;
346  my $sstep = "-sstep " . int $length / ( 3 * $frames ) + 1;
347  $sstep = "-ss " . int $length / 3 if $::settings->{'ppc_bug'};
348  $menc{'frames'} = "-frames $frames $sstep";
349
350  my $basename = basename substitute_filename( $::settings->{'filename'} );
351  $menc{'cache'} = $::settings->{'cache_directory'} . "/" . $basename . "-cache";
352  $menc{'cache'} = $::settings->{'cache_directory'} . "/" . $basename . "-" . $::settings->{'this_block'} . "-cache" if $::settings->{'this_block'};
353
354  $menc{'more_options'} = $::settings->{'more_options'};
355
356  return %menc;
357}
358
359sub get_command {
360  my $command = shift;
361  my %menc    = get_parameters();
362
363  return
364"$::settings->{'mencoder'} $menc{'cache'} $menc{'audio'} $menc{'audio_track'} $menc{'video'} $menc{'vf_filters'} $menc{'more_options'} $menc{'af'} $menc{'audio_track'} $menc{'mpegfile'} -o \"$menc{'output'}\""
365    if $command eq "mencoder" && $::settings->{'cache'} && $::dvd->{'source'} eq "dvd";
366
367  return
368"$::settings->{'mencoder'} $menc{'dvdmenc'} $menc{'chapter'} $menc{'audio_track'} $menc{'subp'} $menc{'subout'} $menc{'info'} $menc{'audio'} $menc{'af'} $menc{'video'} $menc{'vf_filters'}  $menc{'mpegfile'} $menc{'more_options'} -o \"$menc{'output'}\""
369    if $command eq "mencoder";
370
371  return "$::settings->{'mplayer'} $menc{'dvdplay'} $menc{'audio_track'} $menc{'af'} $menc{'chapter'} $menc{'frames'}	-nocache $menc{'embed'}"
372    if $command eq "preview" && $::settings->{'flickbook_preview'} && !$::settings->{'ppc_bug'};
373
374  return "$::settings->{'mplayer'} $menc{'embed'} $menc{'dvdplay'} $menc{'af'} $menc{'audio_track'} $menc{'chapter'} $menc{'subp'} -nocache"
375    if $command eq "preview";
376
377  return "$::settings->{'mplayer'} -quiet \"$menc{'output'}\""
378    if $command eq "view";
379
380  return "$::settings->{'mplayer'} $menc{'dvdplay'} $menc{'chapter'} -v -v -dumpstream -dumpfile \"$menc{'cache'}\""
381    if $command eq "cache";
382
383  return "$::settings->{'mplayer'} $menc{'vf'} cropdetect $menc{'dvdplay'} -nosound -vo null $menc{'frames'} -nocache"
384    if $command eq "cropdetect";
385
386  return "$::settings->{'mencoder'} $menc{'cache'} $menc{'audio'} $menc{'audio_track'} $menc{'af'} -ovc frameno -o frameno.avi"
387    if $command eq "mencoder_frameno" && $::settings->{'cache'};
388
389  return "$::settings->{'mencoder'} $menc{'dvdmenc'} $menc{'chapter'} $menc{'audio'} $menc{'audio_track'} $menc{'af'} -ovc frameno -o frameno.avi"
390    if $command eq "mencoder_frameno";
391
392  return "$::settings->{'mencoder'} $menc{'cache'} -oac copy $menc{'video'} $menc{'vf_filters'} $menc{'more_options'} $menc{'audio_track'} $menc{'mpegfile'} -o \"$menc{'output'}\""
393    if $command eq "mencoder_3pass" && $::settings->{'cache'};
394
395  return
396"$::settings->{'mencoder'} $menc{'dvdmenc'} $menc{'chapter'} $menc{'subp'} $menc{'subout'} $menc{'info'} -oac copy $menc{'video'} $menc{'vf_filters'}  $menc{'mpegfile'} $menc{'more_options'} -o \"$menc{'output'}\""
397    if $command eq "mencoder_3pass";
398
399  return "unlink \"$menc{'cache'}\"" if $command eq "del_cache";
400
401  return "command not found!";
402}
403
404sub set_bitrate {
405  return -1 if !defined $::dvd->{'track'};
406  my $length;
407  my $size;
408  my $bitrate    = 0;
409  my $audio_rate = 128;
410  my $this_track = get_track();
411
412  if ( $::settings->{'audio_codec'} eq 'mp3lame' && $::settings->{'audio_mp3lame_options'} =~ /br=(\d+)/ ) {
413    $audio_rate = $1;
414  }
415  elsif ( $::settings->{'audio_codec'} eq 'lavc' && $::settings->{'audio_lavc_options'} =~ /abitrate=(\d+)/ ) {
416    $audio_rate = $1;
417  }
418  elsif ( $::settings->{'audio_codec'} eq 'copy' ) {
419    my $channels = $this_track->{'audio'}[ $::settings->{'selected_audio'} ]->{'channels'};
420    $audio_rate = 192 if $channels == 2;
421    $audio_rate = 384 if $channels == 6;
422  }
423
424  if ( $::settings->{'this_block'} ) {
425    $length = get_selection_length( $::settings->{'blocks'}[ $::settings->{'this_block'} - 1 ] + 1, $::settings->{'blocks'}[ $::settings->{'this_block'} ] );
426    $size = $::settings->{'filesize'};
427  }
428  elsif ( $::settings->{'total_blocks'} > 1 ) {
429    $length = get_selection_length();
430    $size = $::settings->{'filesize'} * ( scalar @{ $::settings->{'blocks'} } - 1 );
431  }
432  else {
433    $length = get_selection_length();
434    $size   = $::settings->{'filesize'};
435  }
436
437  if ( $::settings->{'video_bitrate_lock'} ) {
438    set_filesize( $length, $audio_rate );
439		set_bpp();
440    return -1;
441  }
442
443  if ( $size == 0 || $length == 0 || $size !~ /^\d+$/ ) { $bitrate = -1 }
444  else { $bitrate = int( ( ( $size * 8192 ) / $length ) - $audio_rate ) }
445  $bitrate = 5000 if $bitrate > 5000;
446  if ( $bitrate < 0 ) { message("Error setting bitrate") }
447  set_setting( 'video_bitrate', $bitrate );
448  set_bpp();
449}
450
451sub set_filesize ($$) {
452  my $length     = shift;
453  my $audio_rate = shift;
454  my $bitrate    = $::widgets->{'video_bitrate_spin'}->get_value_as_int;
455  my $size;
456
457  if ( $bitrate == 0 || $length == 0 || $audio_rate !~ /^\d+$/ ) {
458    $size = -1;
459  }
460  else {
461    $size = int( ( ( $audio_rate + $bitrate ) * $length ) / 8192 );
462  }
463  if ( $size < 0 ) { message("Error estimating filesize") }
464  set_setting( 'filesize', $size );
465
466  #set_bpp();
467}
468
469sub set_bpp {
470  return -1 if ! defined $::dvd->{'track'};
471  return -1 if ! scalar @{$::dvd->{'track'}};
472
473  my $bpp = 0;
474  my $fps = get_track()->{'fps'} || -1;
475  my $wo  = get_track()->{'width'} || -1;
476  my $ho  = get_track()->{'height'} || -1;
477  my $ws  = $::settings->{'scale_width'} || $wo;
478  my $hs  = $::settings->{'scale_height'} || $ho;
479  my $br  = $::settings->{'video_bitrate'};
480  my $wc  = $::settings->{'crop_width'} || $wo;
481  my $hc  = $::settings->{'crop_height'} || $ho;
482  my $aa  = 0;
483  if ( defined get_track()->{'aspect'} ) {
484    my $aa = eval( get_track()->{'aspect'} );    #eval to allow fraction string to equate to a float
485  }
486  $aa = $wo / $ho if !$aa;
487
488  if ( defined $aa && $br * $hc * $wc * $wo * $ho * $fps )    # moronic test for potential divide by zero!
489  {
490    $hs = $hs || $hc;
491    $ws = $ws || $ho * $wc * $aa / $wo;
492    $hs = $hc if $hs == -1;
493    $ws = $wc if $ws == -1;
494    $hs = ( $hc * $wo * $ws ) / ( $wc * $ho * $aa ) if $hs == -2;
495    $ws = ( $wc * $ho * $hs * $aa ) / ( $hc * $wo ) if $ws == -2;
496
497    $ws = sprintf( "%i", $ws );
498    $hs = sprintf( "%i", $hs );
499    $bpp = sprintf( "%.3f", ( $br * 1000 ) / ( $hs * $ws * $fps ) ) if $ws * $hs;
500
501    if ( defined $::widgets && $ws > 0 && $hs > 0 ) {
502      $::widgets->{'scale_height_estimate_entry'}->set_text($hs);
503      $::widgets->{'video_bpp_entry'}->set_text($bpp);
504    }
505  }
506  return $ws, $hs, $wc, $hc, $wo, $ho;
507}
508
509sub get_available_codecs {
510  my $count = 0;
511
512  #my $item;
513  my $menc = $::settings->{'mencoder'};
514  system "$menc >/dev/null 2>&1";
515  print "MEncoder was not found! Acidrip is utterly useless without it! go install!\n" if $? >> 8 != 1;
516  if ( open( MENC_VIDEO, "$menc -ovc help 2>&1 |" ) ) {
517    while (<MENC_VIDEO>) {
518      $::settings->{'mplayer_version'} = $1 if $_ =~ /MEncoder\s(\d\.\d)/;
519      if ( $_ =~ /\s+(\w+)\s+-\s+(.+)/ ) {
520        $::settings->{'available_video'}{$1} = "$1 - $2";
521        if ( defined $::widgets and $1 ne "frameno" ) {
522          my $item = new Gtk2::MenuItem("$1");
523          $::widgets->{'video_codec_option'}->get_menu->append($item);
524          $item->signal_connect( 'activate', \&on_option_changed, $1 );
525
526          $::widgets->{'video_options_entry'}->set_text( $::settings->{ $::settings->{'video_codec'} . '_options' } or "" );
527          $::widgets->{'video_codec_option'}->set_history($count) if $1 eq $::settings->{'video_codec'};
528          $count++;
529        }
530      }
531    }
532    $::widgets->{'video_codec_option'}->show_all if defined $::widgets;
533    close MENC_VIDEO;
534  }
535  else { message("Mencoder codec test failed. Is MPlayer installed properly?") }
536
537  if ( open( MENC_AUDIO, "$menc -oac help 2>&1 |" ) ) {
538    my $got_mp3 = 0;
539    $count = 0;
540    while (<MENC_AUDIO>) {
541      if ( $_ =~ /\s+(\w+)\s+-(.*)/ ) {
542        $::settings->{'available_audio'}{$1} = "$1 - $2";
543        $got_mp3 = 1 if $1 eq "mp3lame" or $1 eq "lavc";
544        if ( defined $::widgets ) {
545          my $item = new Gtk2::MenuItem("$1");
546          ( $::widgets->{'audio_codec_option'}->get_menu )->append($item);
547          $item->signal_connect( 'activate', \&on_option_changed, $1 );
548        }
549
550        $::widgets->{'audio_options_entry'}->set_text( $::settings->{ "audio_" . $::settings->{'audio_codec'} . '_options' } or '' );
551        $::widgets->{'audio_codec_option'}->set_history($count) if $1 eq $::settings->{'audio_codec'};
552        $count++;
553      }
554    }
555    $::widgets->{'audio_codec_option'}->show_all if defined $::widgets;
556    print "AcidRip could NOT find MP3 support in MPlayer! if you do want MP3 sound in your films,"
557      . "you will need to recompile MPlayer accordingly. See the docs on the MPlayer site.\n\n"
558      if !$got_mp3;
559    close MENC_AUDIO;
560  }
561  else { message("Mencoder codec test failed. Is MPlayer installed properly?") }
562}
563
564sub kill_mplayer {
565  if ( $::settings->{'mencoder_pid'} > 0 ) {
566    my $m = $::settings->{'mencoder_pid'} + 1;
567    kill 'INT', $::settings->{'mencoder_pid'};
568    kill 'INT', $m if `ps $m | grep mencoder` || `ps $m | grep mplayer`;
569    message("Encoding stopped.");
570    $::settings->{'mencoder_pid'} = -1;
571  }
572  else {
573    message("Nothing to stop!");
574  }
575}
576
577sub get_selection_length {
578  my ( $start, $end ) = @_;
579  my $length = 0;
580  if ( defined get_track()->{'chapter'} ) {
581    $start = ( $::settings->{'selected_chapters_start'} || 1 ) if !$start;
582    $end = ( $::settings->{'selected_chapters_end'} || get_track->{'chapter'}[-1]->{'ix'} ) if !$end;
583    for my $chapter ( $start .. $end ) {
584      $length += get_chapter($chapter)->{'length'};
585    }
586  }
587  else {
588    $length = get_track_param('length');
589  }
590  return $length;
591}
592
593sub read_source ($) {
594  my $path = shift;
595  if ( -b $path || -c $path ) {
596    return read_disc($path);
597  }
598  elsif ( -d $path ) {
599    my $return = read_disc($path);
600    if ($return) {
601      return read_src_file($path);
602    }
603    else {
604      return $return;
605    }
606  }
607  else {
608    return read_src_file($path);
609  }
610}
611
612sub read_disc ($) {
613  use vars qw(%lsdvd);
614  my $dvd_device = shift;
615  system("$::settings->{'lsdvd'} -h > /dev/null 2> /dev/null");
616  if ( !$? ) {
617    eval(`$::settings->{'lsdvd'} -xp $dvd_device 2>/dev/null`);
618    if ( !$? ) {
619      $::dvd                = {%lsdvd};
620      $Data::Dumper::Indent = 0;
621      my $lsout = Dumper { %lsdvd };
622      $::widgets->{'mencoder_output_text'}->get_buffer->insert_with_tags_by_name( $::widgets->{'mencoder_output_text'}->get_buffer->get_end_iter, $lsout . "\n", 'lsdvd' );
623      $::dvd->{'status'}    = "DVD read ok";
624      $::dvd->{'source'}    = "dvd";
625      $Data::Dumper::Indent = 2;
626    }
627    else {
628      $::dvd = undef;
629    }
630  }
631  else {
632    $::dvd = undef;
633  }
634  $::dvd->{'status'} = "lsdvd not found"             if $? >> 8 == 127;
635  $::dvd->{'status'} = "DVD device not found"        if $? >> 8 == 1;
636  $::dvd->{'status'} = "DVD not found. Drive empty?" if $? >> 8 == 2;
637  system( "eject " . $dvd_device ) if $? >> 8 == 2 && $::settings->{'eject'};
638  $::dvd->{'status'} = "Can't read DVD. Not a valid DVD drive!" if $? >> 8 == 3;
639  $::dvd->{'status'} = "Can't read DVD track. Faulty Disc?"     if $? >> 8 == 4;
640
641  return $?;
642}
643
644sub read_src_file ($) {
645  my %files;
646  my $path = shift;
647  $files{'device'} = $path;
648  $files{'source'} = "file";
649
650  open IDENTIFY, "$::settings->{'mplayer'} -identify -ao null -vo null -frames 0 $path" . ( -d $path ? '/*' : '' ) . " 2>&1 |";
651
652  while (<IDENTIFY>) {
653    $files{'track'}[ scalar @{ $files{'track'} } ]{'filename'} = $1 if /ID_FILENAME=(.+)/;
654    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'ix'} = scalar @{ $files{'track'} } if /ID_FILENAME=(.+)/;
655   	$files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'fps'}    = $1 if /ID_VIDEO_FPS=(.+)/;
656    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'width'}  = $1 if /ID_VIDEO_WIDTH=(.+)/;
657    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'height'} = $1 if /ID_VIDEO_HEIGHT=(.+)/;
658    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'aspect'} = $1 if /ID_VIDEO_ASPECT=(.+)/ && $1;
659    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'format'} = ( $1 eq '0x10000001' ? "MPEG1" : ( $1 eq '0x10000002' ? "MPEG2" : $1 ) ) if /ID_VIDEO_FORMAT=(.+)/;
660    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'bitrate'} = $1 if /ID_VIDEO_BITRATE=(.+)/ && $1;
661    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'audio'}[0]{'format'}    = $1 if /ID_AUDIO_CODEC=(.+)/;
662    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'audio'}[0]{'ix'}        = 1  if /ID_AUDIO_CODEC=(.+)/;
663    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'audio'}[0]{'aformat'}   = $1 if /ID_AUDIO_FORMAT=(.+)/;
664    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'audio'}[0]{'bitrate'}   = $1 if /ID_AUDIO_BITRATE=(.+)/;
665    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'audio'}[0]{'frequency'} = $1 if /ID_AUDIO_RATE=(.+)/;
666    $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'audio'}[0]{'channels'}  = $1 if /ID_AUDIO_NCH=(.+)/;
667    if (/ID_LENGTH=(.+)/) { # this is the final line in the output, so might as well demlimit the files
668      $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'length'} = $1;
669      if ( defined $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'format'} &&
670						defined $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'fps'} &&
671						defined $files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'bitrate'} &&
672						$files{'track'}[ scalar @{ $files{'track'} } - 1 ]{'format'} ne 'DVSD') {
673        message("Scanning file \'$files{'track'}[scalar @{$files{'track'}} -1]{'filename'}\'");
674      }
675      else {
676        pop @{ $files{'track'} };
677      }
678    }
679    while ( Gtk2->events_pending() ) { Gtk2->main_iteration() }
680	}
681
682  close IDENTIFY;
683  $::dvd = {%files};
684  if ( defined $files{'track'} ) {
685    $::dvd->{'status'} = scalar @{ $files{'track'} } . " file" . ( scalar @{ $files{'track'} } != 1 ? 's' : '' ) . " read OK";
686  }
687  else {
688    $::dvd->{'status'} = "No valid files found";
689    $::dvd->{'status'} = "No read access to $path" if !-r $path;
690    $::dvd->{'status'} = "$path does not exist!" if !-e $path;
691  }
692
693  return 0;
694}
695
696sub find_crop ($) {
697  open STDIN, '/dev/null' or message("Can't read /dev/null: $!. May fail if in background");
698
699  my $crop_output;
700  if ( defined $::dvd->{'track'} ) {
701    my %crop;
702    message( "Running " . get_command("cropdetect") );
703    open( CROP, get_command("cropdetect") . " 2>&1 |" );
704    while (<CROP>) {
705      if ( $_ =~ /crop area.*\s(crop=\d*:\d*:\d*:\d*)/ ) { $crop{$1}++ }
706      $crop_output .= $_;
707      gui_check($_);
708    }
709    my @order = sort { $crop{$b} <=> $crop{$a} } keys %crop;
710    close CROP;
711    return ( $order[0], $crop_output );
712  }
713  else { return ( -1, "crop detect failed" ) }
714}
715
716sub rebuild_queue_text {
717  my $buffer = $::widgets->{'queue_text'}->get_buffer;
718  $buffer->delete( $buffer->get_bounds );
719
720  for ( 1 .. @{$::playlist} ) {
721    my %item = %{ @{$::playlist}[ $_ - 1 ] };
722    $buffer->insert( $buffer->get_end_iter, $item{'command'} . "\n" );
723  }
724}
725
726sub queued_encode_events {
727	my $events = 0;
728	foreach my $event (@{$::playlist}) {
729		my %e= %{$event};
730		if ( $e{'command'} =~ /mencoder/ || $e{'command'} =~ /mplayer/ ) {
731			$events++;
732		}
733	}
734	return $events;
735}
736
737sub push_playlist_queue {
738  message("Pushed events onto queue");
739
740  if ( !defined $::dvd->{'track'} ) {
741    message("Hey, you gotta load DVD or file(s) first!");
742    return -1;
743  }
744
745  my %menc = get_parameters();
746
747  if ( -e $menc{'output'} && !$::settings->{'overwrite'} && $menc{'output'} ne "/dev/null" ) {
748    message("File already exists, refusing to overwrite");
749    return -1;
750  }
751  my $directory = dirname( substitute_filename( $::settings->{'filename'} ) );
752  if ( !-d $directory ) {
753    message("Output directory does not exist!");
754    return -1;
755  }
756  if ( !-w $directory ) {
757    message("Can't write to output directory!");
758    return -1;
759  }
760  if ( ( !$::settings->{'enough_space'} ) && $::settings->{'enforce_space'} ) {
761    message("Not enough space in output directory!");
762    return -1;
763  }
764
765  # Encode file
766  for ( 1 .. $::settings->{'total_blocks'} ) {
767    $::settings->{'this_block'} = $_ if $::settings->{'total_blocks'} > 1;
768
769    if ( $::settings->{'cache'} && $::dvd->{'source'} eq "dvd" ) {
770			$::settings->{'total_events'}++;
771      $::playlist->prepend( get_command('cache'), 'cache', "Caching title..." ) if $::settings->{'precache'};
772      $::playlist->append( get_command('cache'), 'cache', "Caching title..." ) if !$::settings->{'precache'};
773      $::playlist->append( "eject $::settings->{'dvd_device'}", 'system', 'Ejecting DVD' )
774        if $::settings->{'eject'} && $::dvd->{'source'} eq "dvd" && (
775        ( $::settings->{'this_block'} == $::settings->{'total_blocks'} && !$::settings->{'precache'} ) ||    # last block on precache
776        ( $::settings->{'this_block'} == 1                             && $::settings->{'precache'} )  ||    # first block of normal cache
777        $::settings->{'total_blocks'} == 1                                                                   # single block
778        );
779    }
780
781    my $message = "Encoding film";
782    $message .= ", Block " . $::settings->{'this_block'} . " of " . $::settings->{'total_blocks'} if $::settings->{'this_block'} > 0;
783
784    my $twopassable = ( $::settings->{'video_codec'} eq "lavc" || $::settings->{'video_codec'} eq "divx4" || $::settings->{'video_codec'} eq "xvid" );
785
786    $::playlist->append( "unlink frameno.avi 2> /dev/null", 'system', "Removing frameno.avi if it exists" )
787        if $::settings->{'this_block'} == 1 || $::settings->{'total_blocks'} == 1;
788
789		if ( $::settings->{'video_passes'} > 1 && $twopassable ) {
790
791      $::playlist->append( get_command("mencoder_frameno"), 'encode', $message . ", frameno pass..." ) if $::settings->{'video_passes'} == 3;
792
793      $::settings->{'video_pass'} = 1;
794      $::playlist->append( get_command( "mencoder" . ( $::settings->{'video_passes'} == 3 ? "_3pass" : "" ) ), 'encode', $message . ", 1st pass..." );
795
796      $::settings->{'video_pass'} = 2;
797      $::playlist->append( get_command( "mencoder" . ( $::settings->{'video_passes'} == 3 ? "_3pass" : "" ) ), 'encode', $message . ", 2nd pass..." );
798
799      $::playlist->append( "unlink frameno.avi 2> /dev/null", 'system', "Removing frameno.avi" ) if $::settings->{'video_passes'} == 3;
800
801      $::playlist->append( "unlink divx2pass.log  2> /dev/null", 'system', "Removing divx2pass.log" );
802    }
803    else {
804      $::playlist->append( get_command("mencoder"), 'encode', $message );
805    }
806    $::playlist->append( get_command("del_cache"), 'system', "Deleting cache file" ) if $::settings->{'cache'} && $::settings->{'del_cache'} && $::dvd->{'source'} eq "dvd";
807  }
808  $::playlist->append( "eject $::settings->{'dvd_device'} 2> /dev/null", 'system', 'Ejecting DVD' ) if $::settings->{'eject'} && !$::settings->{'cache'};
809  $::playlist->append( "shutdown -h now", 'system', 'Shutting down... bye!' ) if $::settings->{'shutdown'};
810}
811
812sub pop_playlist_queue {
813  my %item = $::playlist->get();
814  message( "Running " . $item{'command'} );
815  message( $item{'message'} );
816  encode( $item{'command'} ) if $item{'type'} eq 'encode';
817  cache( $item{'command'} )  if $item{'type'} eq 'cache';
818  system( $item{'command'} ) if $item{'type'} eq 'system';
819  $item{'type'} ne 'system' ? return $? : return 0;
820}
821
822sub cache {
823
824  #fork proofing
825  open STDIN, '/dev/null' or message("Can't read /dev/null: $!. May fail if in background");
826
827  my $cache = shift;
828  $cache =~ /"(.+)"/;
829  my $file      = $1;
830  my $this_cell = -1;
831  my $size      = 0;
832  my $start_chapter;
833  my $stop_chapter;
834  my $this_track = get_track();
835
836  if ( $::settings->{'total_blocks'} > 1 ) {
837		$cache =~/-(\d+)-cache/;
838	  $start_chapter = $::settings->{'blocks'}[ $1 - 1 ] + 1;
839    $stop_chapter  = $::settings->{'blocks'}[ $1 ];
840  }
841  else {
842    $start_chapter = $::settings->{'selected_chapters_start'};
843    $stop_chapter  = $::settings->{'selected_chapters_end'};
844    $start_chapter = 1 if $start_chapter == 0;
845    $stop_chapter  = $this_track->{'chapter'}[-1]->{'ix'} if $stop_chapter == 0;
846  }
847  my $total_chapters = $stop_chapter - $start_chapter + 1;
848	my $this_event = $::settings->{'total_events'} - queued_encode_events();
849  $::settings->{'mencoder_pid'} = open( CACHE, "nice $cache 2>&1 |" );
850  while (<CACHE>) {
851    if (/### CELL (\d+)/) {
852      if ( $this_cell != $1 + 1 ) {
853        $this_cell = $1 + 1;
854        my $this_chapter = 0;
855      LOOP: foreach ( reverse( @{ $this_track->{'chapter'} } ) ) {
856          $this_chapter = $_->{'ix'};
857          last LOOP if $_->{'startcell'} <= $this_cell;
858        }
859				$::widgets->{'cache_chapter'}->set_text( sprintf( "%d (%d/%d)", $this_chapter, $this_chapter + 1 - $start_chapter, $total_chapters ) );
860				my $progress = sprintf("%d", ($this_event - 1 + ($this_chapter - $start_chapter) / $total_chapters)*100/$::settings->{'total_events'});
861				$::widgets->{'acidrip'}->set_title(msg("acidrip") . ' - ' . $progress . '%');
862				$::widgets->{'progress_dialog'}->set_title(msg("acidrip") . ' - ' . $progress . '%');
863      }
864      $::widgets->{'cache_size'}->set_text( sprintf( "%d", ( -s $file ) / 1048576 ) . "Mb" ) if -e $file;
865    }
866    while ( Gtk2->events_pending() ) { Gtk2->main_iteration() }
867  }
868  close CACHE;
869
870  return $file;
871}
872
873sub encode {
874
875  #fork proofing
876  open STDIN, '/dev/null' or message("Can't read /dev/null: $!. May fail if in background");
877
878  my $menc = shift;
879
880  if ( defined $::widgets ) {
881    my $buffer = $::widgets->{'mencoder_output_text'}->get_buffer;
882    my ( $sec, $fps, $size, $time, $rate, $prog ) = ( 0, 0, 0, 0, 0, -1 );
883		my $this_event = $::settings->{'total_events'} - queued_encode_events();
884
885    if ( $::settings->{'mencoder_pid'} = open( MENCODER, "$menc 2>&1 |" ) ) {
886      $/ = "\r";
887			while (<MENCODER>) {
888        if (/^Pos:\s*(\d+).\ds\s+(\d+)f\s+\(\s*(\d+)%\)\s+(\d+fps)\sTrem:\s+(\d+min)\s+(\d+mb).+\[([\d:]+)\]/) {
889          if ( $1 ne $sec )  { $sec  = $1; $::widgets->{'menc_seconds'}->set_text( hhmmss($1) ) }
890          if ( $4 ne $fps )  { $fps  = $4; $::widgets->{'menc_fps'}->set_text($4) }
891          if ( $6 ne $size ) { $size = $6; $::widgets->{'menc_filesize'}->set_text($6) }
892          if ( $5 ne $time ) { $time = $5; $::widgets->{'menc_time'}->set_text($5) }
893          if ( $7 ne $rate ) { $rate = $7; $::widgets->{'menc_bitrate'}->set_text($7) }
894          if ( $3 ne $prog ) {
895						$prog = $3;
896						$::widgets->{'menc_progress'}->set_fraction( $3 / 100 );
897				    my $progress = sprintf("%d", ($this_event - 1 + ($3/100))*100/$::settings->{'total_events'});
898				    $::widgets->{'acidrip'}->set_title(msg("acidrip") . ' - ' . $progress . '%');
899						$::widgets->{'progress_dialog'}->set_title(msg("acidrip") . ' - ' . $progress . '%');
900					}
901        }
902        else { s/\r/\n/g; $buffer->insert_with_tags_by_name( $buffer->get_end_iter, $_, 'mplayer' ) }
903        while ( Gtk2->events_pending() ) { Gtk2->main_iteration() }
904      }
905      $/ = "\n";
906    }
907    else { message( "Mencoder failed, is it properly installed?", 'error' ) }
908  }
909  else {
910    message( "Mencoder failed, is it properly installed?", 'error' ) if !( $::settings->{'mencoder_pid'} = open( MENCODER, "$menc" ) );
911  }
912  $::widgets->{'view_button'}->set_sensitive( -r ( substitute_filename( $::settings->{'filename'} . ( $::settings->{'mpegfile'} ? ".mpg" : ".avi" ) ) ) ? 1 : 0 );
913  close MENCODER;
914}
915
916package acidrip_settings;
917
918use vars qw($defaults);
919
920$defaults = {
921  'dvd_device'              => '/dev/acd0',
922  'selected_track'          => 0,
923  'selected_chapters_start' => 0,
924  'selected_chapters_end'   => 0,
925  'filesize'                => 700,
926  'total_blocks'            => 1,
927  'this_block'              => 0,
928  'blocks'                  => [],
929  'selected_audio'          => -1,
930  'selected_subp'           => -1,                                # Remember, the GUI is 1 based, mplayer is 0 based.
931  'audio_codec'             => 'mp3lame',
932  'audio_gain'              => 0,
933  'audio_options'           => '',
934  'audio_mp3lame_options'   => 'abr:br=128',
935  'audio_lavc_options'      => 'acodec=mp3:abitrate=128',
936  'video_codec'             => 'lavc',
937  'lavc_options'            => 'vcodec=mpeg4:vhq:v4mv:vqmin=2',
938  'divx4_options'           => '',
939  'xvid_options'            => '',
940  'vuv_options'             => '',
941  'video_options'           => '',
942  'video_bitrate'           => 0,
943  'video_bitrate_lock'      => 0,
944  'filename'                => $ENV{HOME} . '/%T',
945  'title'                   => 'unknown',
946  'mpegfile'                => 0,
947  'length'                  => 0,
948  'scale_enable'            => 1,
949  'scale_auto'              => 1,
950  'scale_height'            => -2,
951  'scale_width'             => 480,
952  'crop_enable'             => 1,
953  'crop_height'             => 0,
954  'crop_width'              => 0,
955  'crop_vertical'           => 0,
956  'crop_horizontal'         => 0,
957  'vf_pre'                  => 'pp=de',
958  'vf_pre_enable'           => 1,
959  'vf_post'                 => '',
960  'vf_post_enable'          => 0,
961  'video_pass'              => 0,
962  'video_passes'            => 1,
963  'more_options'            => '',
964  'language'                => 'English',
965  'mencoder'                => 'mencoder',
966  'mplayer'                 => 'mplayer',
967  'lsdvd'                   => 'lsdvd',
968  'available_audio'         => {},
969  'available_video'         => {},
970  'mencoder_pid'            => 0,
971  'autoload'                => 0,
972  'overwrite'               => 0,
973  'enforce_space'           => 1,
974  'cache'                   => 0,
975  'precache'                => 1,
976  'cache_directory'         => '/tmp/',
977  'del_cache'               => 0,
978  'tooltips'                => 1,
979  'busy'                    => 0,
980  'UI'                      => 1,
981  'compact'                 => 1,
982  'enough_space'            => 1,
983  'ppc_bug'                 => 0,
984  'embed_preview'           => 1,
985  'eject'                   => 0,
986  'vobsubout'               => 0,
987  'mplayer_version'         => 1,
988  'flickbook_preview'       => 0,
989  'export_script'           => 0,
990  'info_artist'             => '',
991  'info_genre'              => '',
992  'info_name'               => '',
993  'info_copyright'          => '',
994  'info_subject'            => '',
995  'shutdown'                => 0,
996	'ui_language'             => 'English',
997	'total_events'            => 0
998};
999
1000sub new {
1001  my $class    = shift;
1002  my $settings = {};
1003  foreach my $key ( keys %{$defaults} ) { $settings->{$key} = $defaults->{$key} }
1004  bless( $settings, $class );
1005  return $settings;
1006}
1007
1008sub get_default ($$) {
1009  my ( $settings, $value ) = @_;
1010  return $defaults->{$value} if ( defined $settings->{$value} );
1011  return "unknown setting! - $value";
1012}
1013
1014sub restore_settings {
1015  my $settings = shift;
1016  foreach my $key ( keys %{$defaults} ) { $settings->{$key} = $defaults->{$key} unless $key eq "selected_track" }
1017  return $settings;
1018}
1019
1020sub save_settings {
1021  my $settings = shift;
1022  my @save     = (
1023    'dvd_device',    'filesize',     'filename',          'audio_codec',        'audio_mp3lame_options', 'audio_lavc_options',
1024    'video_codec',   'scale_enable', 'autoload',          'mpegfile',           'eject',                 'scale_auto',
1025    'scale_height',  'scale_width',  'crop_enable',       'language',           'mencoder',              'mplayer',
1026    'lsdvd',         'tooltips',     'video_passes',      'video_bitrate_lock', 'lavc_options',          'xvid_options',
1027    'divx4_options', 'more_options', 'total_blocks',      'overwrite',          'cache',                 'cache_directory',
1028    'vf_pre_enable', 'audio_gain',   'vf_post_enable',    'vf_pre',             'vf_post',               'del_cache',
1029    'ppc_bug',       'compact',      'flickbook_preview', 'enforce_space',      'vobsubout',             'video_bitrate',
1030	  'ui_language'
1031  );
1032  if ( open( CONFIGFILE, '>', "$ENV{HOME}/.acidriprc" ) ) {
1033    foreach my $key (@save) {
1034      print CONFIGFILE "$key = $settings->{$key}\n" if $settings->{$key} ne '';
1035    }
1036    close CONFIGFILE;
1037  }
1038  else {
1039    acidrip::message("Can't open config file for writing!\n");
1040  }
1041}
1042
1043sub load_settings {
1044  my $settings = shift;
1045  if ( open( CONFIGFILE, "$ENV{HOME}/.acidriprc" ) ) {
1046    while (<CONFIGFILE>) {
1047      if ( $_ =~ /(\w+)\s=\s(.+)/ ) { $settings->{$1} = $2 }
1048    }
1049    close CONFIGFILE;
1050  }
1051  else {
1052    acidrip::message("No configuration file found, nevermind.");
1053  }
1054  return $settings;
1055}
1056
1057package acidrip_playlist;
1058
1059use Data::Dumper;
1060
1061sub new {
1062  bless( [], shift );
1063}
1064
1065sub append {
1066  my $playlist = shift;
1067  my %item;
1068  $item{'command'} = shift;
1069  $item{'type'}    = shift;    # system, encode, cache, eval
1070  $item{'message'} = shift;
1071  push( @{$playlist}, \%item );
1072}
1073
1074sub prepend {
1075  my $playlist = shift;
1076  my %item;
1077  $item{'command'} = shift;
1078  $item{'type'}    = shift;    # system, encode, cache, eval
1079  $item{'message'} = shift;
1080  unshift( @{$playlist}, \%item );
1081}
1082
1083sub clear {
1084  my $playlist = shift;
1085  while ( @{$::playlist} ) {
1086    shift @{$::playlist};
1087  }
1088}
1089
1090sub get {
1091  my $playlist = shift;
1092  return %{ shift @{$playlist} };
1093}
1094
10951;
1096