root/trunk/install/perl/tvrecording.pl

リビジョン 8, 59.4 kB (コミッタ: sorshi, コミット時期: 17 年 前)

新エンコーダによりH.264対応、
複数同時録画時の信頼性向上、など

  • svn:executable 属性の設定値:
Line 
1 #!/usr/bin/perl
2 #
3 # Anime recording system foltia
4 # http://www.dcc-jpl.com/soft/foltia/
5 #
6 #tvrecording.pl
7 # record-v4l2.plに準備処理を加えた録画モジュール。
8 #
9 #usage tvrecording.pl ch length(sec) [clip No(000-)] [filename] [bitrate(5)] [TID] [NO] [/dev/video0]
10 #引数
11 #ch :録画チャンネル 0だとS入力、-1だとコンポジット入力 [必須項目]
12 #length(sec) :録画秒数 [必須項目]
13 #[clip No(000-)] :歴史的に0
14 #[filename] :出力ファイル名
15 #[bitrate(5)] :ビットレート Mbps単位で指定
16 #[TID] :しょぼかるタイトルID
17 #[NO] :その番組の放送話数
18 #[/dev/video0]:キャプチャデバイス
19 #
20 #
21 # DCC-JPL Japan/foltia project
22 #
23 #
24
25
26 #use Time::HiRes qw(usleep);
27
28
29 $path = $0;
30 $path =~ s/tvrecording.pl$//i;
31 if ($pwd  ne "./"){
32 push( @INC, "$path");
33 }
34
35
36 ##
37 #キャプチャカード枚数検出
38 #cat /proc/interrupts  | grep ivtv |wc -l
39 # 11:    1054118          XT-PIC  uhci_hcd, eth0, ivtv0, ivtv1, ivtv2
40 #失敗
41
42 #tvConfig.pl -------------------------------
43 $extendrecendsec = 10;                                                  #recording end second.
44 $startupsleeptime = 52;                                 #process wait(MAX60sec)
45 #$startupsleeptime = 1;                                 #process wait(MAX60sec)
46
47 #-------------------------------
48
49 require 'foltialib.pl';
50
51  &writelog("tvrecording:  DEBUG $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] $ARGV[4] $ARGV[5] $ARGV[6]  $ARGV[7] ");
52
53 sub getChCallsign {
54 if ($ARGV[5]  ne ""){
55         $recchname = $ARGV[5] ;
56         }else{
57         $recchname = $recch."ch";
58 }
59
60 }#endsub getChCallsign
61
62 sub getRecPath{ #capture directory define
63         $recfolderpath = '/home/foltia/php/tv';         
64 }#end sub getRecPath
65
66 #準備
67 &prepare;
68 #もし録画が走ってたら、止める
69 $reclengthsec = &chkrecprocess();
70 &setbitrate;
71 &chkextinput;
72
73 $reclengthsec = $reclengthsec + $extendrecendsec ;
74
75 &writelog("tvrecording:$recch:$reclengthsec:$outputfile:$recdevice:$capturedeviceinputnum:$ivtvrecch:$stdbitrate:$peakbitrate");
76
77 #------------------------------
78
79
80 sub chkextinput{
81
82 if ($recch == 0){
83                 if ($svideoinputnum > -1 && $svideoinputnum < 30){
84                 $capturedeviceinputnum = $svideoinputnum ;
85                 }else{
86                 $capturedeviceinputnum = 7 ;
87                 }
88         $capturedeviceinputName = "S-Video 0";
89         $ivtvrecch = '';
90 }elsif($recch == -1){
91                 if ($comvideoinputnum > -1 && $comvideoinputnum < 30){
92                 $capturedeviceinputnum = $comvideoinputnum;
93                 }else{
94                 $capturedeviceinputnum = 8;
95                 }
96         $capturedeviceinputName = "Composite 0";
97         $ivtvrecch = '';
98 }else{
99                 if ($tunerinputnum > -1 && $tunerinputnum < 30){
100                 $capturedeviceinputnum = $tunerinputnum ;
101                 }else{
102                 $capturedeviceinputnum = 6 ;
103                 }
104         $capturedeviceinputName = "Tuner 0";
105         $ivtvrecch = $recch;
106 }
107 # 1-12chはntsc-bcast-jp
108 if($recch > 12){
109         if ($uhfbandtype == 1){
110         $frequencyTable = "ntsc-cable-jp";
111         }else{
112         $frequencyTable = "ntsc-bcast-jp";
113         }
114 }else{
115         $frequencyTable = "ntsc-bcast-jp";
116 }#if
117         &writelog ("tvrecording DEBUG $frequencyTable $recch");
118
119 }#chkextinput
120
121
122
123 sub chkrecprocessOLD{
124 #もし録画が走ってたら、止める
125 my $mencoderkillcmd = "";
126
127 $mencoderkillcmd =`/usr/sbin/lsof -Fp $recdevice`;
128 $mencoderkillcmd =~ s/p//;
129
130 if ($mencoderkillcmd != ""){
131         #kill process
132         $mencoderkillcmd  = "kill ".$mencoderkillcmd;
133         system ($mencoderkillcmd);
134         chomp($mencoderkillcmd);
135         &writelog ("tvrecording Killed current recording process. process:$mencoderkillcmd");
136                 sleep(1);
137                  my $videodevice =`/usr/sbin/lsof $recdevice`;
138
139                 while ($videodevice =~ /tvrecording/){
140
141                 $videodevice =`/usr/sbin/lsof $recdevice`;
142                 sleep(1);
143                 $sleepcounter++;
144                 $reclengthsec = $reclengthsec - $sleepcounter;
145                 &writelog ("tvrecording videodevice wait:$sleepcounter");
146                 }
147                 $sleepcounter = 0;             
148 }#if ($mencoderkillcmd != "")
149
150 return $reclengthsec;
151
152 }#end chkrecprocess
153
154 sub chkrecprocess{
155 my $mencoderkillcmd = "";
156 my $j = $recunits -1;
157 my $i = 0;
158 my $testrecdevice = "";
159 my @usedevices  ;
160 my @unusedevices;
161 my $n = 0;
162 $recdevice = "";
163 if ($ARGV[7]  ne ""){
164         $recdevice =  $ARGV[7] ;
165 }
166
167 #for ($i = $j ;$i >= 0 ; $i--){
168 for ($i = 0 ;$i <= $j ; $i++){
169 #print "$i,$j\n";
170 $testrecdevice = "/dev/video$i";
171 $mencoderkillcmd =`/usr/sbin/lsof -Fp $testrecdevice`;
172 $mencoderkillcmd =~ s/p//;
173 if ($mencoderkillcmd != ""){
174         push (@usedevices ,  $testrecdevice);
175         &writelog ("tvrecording now using:$testrecdevice");
176 }else{
177         push (@unusedevices ,  $testrecdevice);
178         &writelog ("tvrecording unused:$testrecdevice");
179 }#if
180 }#for
181
182 $i = 0; #初期化
183 $n = @unusedevices;
184 #デバイス指定があるか?
185 if ($recdevice  ne ""){ #指定があったら
186 #そこが使われているかチェック
187 $mencoderkillcmd =`/usr/sbin/lsof -Fp $recdevice`;
188 $mencoderkillcmd =~ s/p//;
189         if ($mencoderkillcmd != ""){ #使われてたら無条件に落とす
190         $mencoderkillcmd  = "kill ".$mencoderkillcmd;
191         system ($mencoderkillcmd);
192         chomp($mencoderkillcmd);
193         &writelog ("tvrecording Killed current recording process. $recdevice:$mencoderkillcmd");
194                 sleep(1);
195         }
196 }else{
197 #地上波or 指定なしなら
198         if (($n == 0) and ($recch > 0)) {#空きデバイスがなくて、地上波なら     
199         $mencoderkillcmd =`/usr/sbin/lsof -Fp /dev/video$i`;#→$i
200         $mencoderkillcmd =~ s/p//;
201                 if ($mencoderkillcmd != ""){ #使われてたら最高位/dev/video$j を無条件に落とす →最低位$i
202                 $mencoderkillcmd  = "kill ".$mencoderkillcmd;
203                 system ($mencoderkillcmd);
204                 chomp($mencoderkillcmd);
205                 &writelog ("tvrecording Killed current recording process. /dev/video$i:$mencoderkillcmd");
206                         sleep(1);
207                 }
208         $recdevice = "/dev/video$i"; #→最低位$i
209                 &writelog ("tvrecording select device:$recdevice");
210
211 }elsif ($recch <= 0) { # 外部入力なら
212         #外部入力だけどデバイス指定されていないときも
213         #落とす
214         $mencoderkillcmd =`/usr/sbin/lsof -Fp /dev/video$j`;#
215         $mencoderkillcmd =~ s/p//;
216                 if ($mencoderkillcmd != ""){ #使われてたら最高位/dev/video$j を無条件に落とす
217                 $mencoderkillcmd  = "kill ".$mencoderkillcmd;
218                 system ($mencoderkillcmd);
219                 chomp($mencoderkillcmd);
220                 &writelog ("tvrecording Killed current recording process. /dev/video$j:$mencoderkillcmd");
221                         sleep(1);
222                 }
223         $recdevice = "/dev/video$j"; # 外部入力は最高位デバイス
224         }else{
225         #空きを使う
226         $recdevice = shift(@unusedevices );
227         }#endif 空きデバイスなければ
228
229 }#end if 指定あるか
230
231 #ここには落ちてこないはずなのに?
232 if ($recdevice eq ""){
233         $recdevice = "/dev/video0";
234         &writelog ( "Rec Device un defined. / $recch ");
235 }
236 return $reclengthsec;
237
238 }#end chkrecprocessNew
239
240
241
242 sub prepare{
243
244 #引数エラー処理
245 $recch = $ARGV[0] ;
246 $reclengthsec = $ARGV[1];
247 if (($recch eq "" )|| ($reclengthsec eq "")){
248         print "usage tvrecording.pl ch length(sec) [clip No(000-)] [filename] [bitrate(5)] [TID] [NO] [/dev/video0]\n";
249         exit;
250 }
251 #1分前にプロセス起動するから指定時間スリープ
252 #srand(time ^ ($$ + ($$ << 15)));
253 #my $useconds  = int(rand(12000000));
254 #my $intval = int ($useconds  / 1000000);
255 #my $startupsleeptimemicro = ($startupsleeptime * 1000000) - $useconds;
256 #$reclengthsec = $reclengthsec + $intval + 1;
257 #&writelog("tvrecording:  DEBUG SLEEP $startupsleeptime:$useconds:$intval:$startupsleeptimemicro");
258 #       usleep ( $startupsleeptimemicro );
259
260 # $recch でウェイト調整入れましょう
261 my $intval = $recch % 50; # 0〜49
262 my $startupsleep = $startupsleeptime - $intval; #  3〜52 (VHF 40-51)
263 $reclengthsec = $reclengthsec + $intval + 1; #
264
265 &writelog("tvrecording:  DEBUG SLEEP $startupsleeptime:$intval:$startupsleep");
266
267 sleep ( $startupsleep);
268
269 if ($recunits > 1){
270 my $deviceno = $recunits - 1;#3枚差しのとき/dev/video2から使う
271         $recdevice = "/dev/video$deviceno";
272         $recch = $ARGV[0] ;
273 }else{
274 #1枚差し
275         $recdevice = "/dev/video0";
276         $recch = $ARGV[0] ;
277 }
278
279 &getChCallsign();
280 #&getRecPath;
281
282 $outputpath = "$recfolderpath"."/";
283
284 if ($ARGV[6] eq "0"){
285         $outputfile = $outputpath.$ARGV[5]."--";
286 }else{
287         $outputfile = $outputpath.$ARGV[5]."-".$ARGV[6]."-";
288 }
289 #2番目以降のクリップでファイル名指定があったら
290         if ($ARGV[3]  ne ""){
291 #               if ($ARGV[3] =~ /[0-9]{8}-[0-9]{4}/){
292 #               $outputfile .= "$ARGV[3]";
293 #               }else{
294 #               $outputfile .= `date  +%Y%m%d-%H%M --date "1 min "`;
295 #               }
296                 $outputfile = $ARGV[3];
297                 $outputfile = &filenameinjectioncheck($outputfile);
298                 $outputfile = $outputpath.$outputfile ;
299 #               $outputfile .= "$ARGV[3]";             
300 #               $outputfile .= `date  +%Y%m%d-%H%M --date "1 min "`;
301  &writelog("tvrecording:  DEBUG ARGV[2] ne null  \$outputfile $outputfile ");
302
303         }else{
304         $outputfile .= `date  +%Y%m%d-%H%M --date "1 min "`;
305         chomp($outputfile);
306         $outputfile .= ".m2p";
307 &writelog("tvrecording:  DEBUG ARGV[2] is null  \$outputfile $outputfile ");
308
309         }
310
311
312 @wday_name = ("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
313 $sleepcounter = 0;
314 $cmd="";
315
316 #二重録りなど既に同名ファイルがあったら中断
317 if ( -e "$outputfile" ){
318 &writelog("tvrecording :ABORT :recfile $outputfile exist.");
319 exit 1;
320 }
321
322 }#end prepare
323
324 sub setbitrate{
325 $bitrate = $ARGV[4] ;
326 $bitrate = $bitrate * 1024*1024;#Mbps -> bps
327 $peakbitrate = $bitrate + 350000;
328 $recordbitrate = "  --bitrate $bitrate --peakbitrate $peakbitrate ";
329         $stdbitrate = "$bitrate";
330         $peakbitrate = "$peakbitrate";
331 }#end setbitrate
332
333 #-------------------------------------------------------------------------------------------------
334 # record-v4l2.pl created by James A. Pattie <james@pcxperience.com> 04/10/2003
335 # Copyright 2003
336 # Purpose: to record from the specified channel for the specified amount
337 # of time to the video OutputDirectory under the channel-start time name as video.mpg.
338
339 #
340 # You can always get the latest version of this script at
341 # http://www.pcxperience.org/
342 #
343
344 #2003.11.18     patched by DCC-JPL
345
346 # 20030425 - 1.4 - Added devfs support based upon patch submitted by
347 #                  Jonathan Kolb <jkolb-ivtv@greyshift.net>
348 # 20030426 - 1.5 - Imported the ptune.pl functionality
349 # 20030426 - 1.6 - moved -F -> -L, -F now lets you specify the frequency to tune to.
350 # 20030427 - 1.7 - renamed to record_ivtv.pl per Kevin's request.  Added -R option.
351 # 20030430 - 1.8 - fixing some comparisons that needed to be strings, etc.
352 # 20030504 - 1.9 - Migrating to Video::ivtv for video resolution support.
353 # 20030505 - 1.10- Replaced open w/ sysopen but it doesn't make a difference.
354 #                  Starting to replace the Standard code w/ Video::ivtv methods.
355 #                  Added the version numbers that I require to the use statements.
356 # 20030507 - 1.11- Migrated to using get/setFrequency from Video::ivtv 0.03.
357 # 20030510 - 1.12- Migrated to using get/setInput from Video::ivtv 0.04.  Moved to using
358 #                  the exported method names rather than Video::ivtv::method().
359 #                  Converted to using enumerateStandard().
360 #                  Fixed the condition where switching Video Standards will most likely
361 #                  not get the correct channel and so would switch back with channel = 0
362 #                  which is invalid.  In this case I store the previous frequency, do the
363 #                  channel change but signal to restore the previous frequency on cleanup.
364 #                  Converted to using enumerateInput().
365 # 20030512 - 1.13- Added initial support for setting the bitrate/bitrate_peak values.
366 # 20030513 - 1.14- Tweaked the bitrate values to be closer to real DVD bitrates.
367 #                  Added support for the .ivtvrc config file and User Profiles.
368 # 20030516 - 1.15- Updated to the OO interface that Video::ivtv 0.06 now requires.
369 #                  Cleaned up a lot of the global variables into a settings hash.
370 #                  Made the -S command add any config items you specified on the command line
371 #                  that were not in the Profile being updated.  This way you can add new items.
372 #                  Made the config file work from a mapping hash so that we can easily add/remove
373 #                  config items in the future.
374 # 20030518 - 1.16- Fixed a Frequency bug that happened when changing Video Standards and the
375 #                  Frequency came from a user specified Profile.
376 # 20030519 - 1.17- Adding the rest of the Codec related options to the config file / defaults.
377 #                  Switched to using Getopt::Long.  You can specify all config file options at
378 #                  least by a --long version and still by the original -X command option.
379 #                  Cleaned up the option parsing code to take advantage of the mappings hash.
380 # 20030520 - 1.18- Fixing the handling of the Profile command line option.
381 # 20030524 - 1.19- Cleaned up the output for -L/--list-freqtable.  Changed --list -> --list-freqtable.
382 #                  Added support to detect the v4l2 driver in use and disable the ivtv "enhancements"
383 #                  if driver != "ivtv".
384 #                  Renamed to record-v4l2.pl to reflect the ability of this program to record from any
385 #                  v4l2 device but with special support for the ivtv driver.
386 # 20030524 - 1.20- Improving the Ctrl-C handling (cleanup before dying).  It may take a second or two
387 #                  before the program exits, but it should exit after resetting anything it changed, unless
388 #                  you had specified not to reset the card.
389 #                  Allow layering of profiles by calling -P/--profile multiple times.  Each profile will
390 #                  be layered over the last.  You will not be able to create/update a profile if you
391 #                  specify more than one though.
392 #                  Fixed a bug that would cause a parameter from the profile to be set n times, where n was
393 #                  the number of characters in the mapping string that consisted of the single letter | and
394 #                  the long command option name.  Ex:  Channel has 'c|channel' so the Channel value was being
395 #                  set 9 times instead of just the first time if it was in the profile.
396 # 20030525 - 1.21- Fixed devfsd detection code as it was overriding what came from the config file.
397 #                  Adding --no-record option so that we can start to implement the replacement functionality for
398 #                  ptune.pl (ie.  Set all values and then exit, do not reset the card and do not capture)
399 # 20030607 - 1.22- Adding --directory-format and --date-format options so that the user can specify the
400 #                  naming convention to use when specifying the directory the output file should be put in.
401 #                  Tweaked some of the defaults.
402 #                  Create the config file if it doesn't exist, regardless of the --save flag being specified.
403 #                  Added method error() to output an error condition that doesn't warrant the whole usage and
404 #                  converted all relevant usage() calls to error() calls.
405 #                  Added option --debug to dynamically on the fly enable debug output.
406 # 20030609 - 1.23- Added option --list-channels to display the currently selected frequency tables contents.
407 #                  Changed the default output directory to '.'.
408 #                  Moved $debug -> $settings{Debug} so it can be stored in the config file.  This allows you to
409 #                  turn debugging on for only certain profiles, etc.
410 #                  Restructured some of the validity tests to only happen as long as we are recording since they
411 #                  do not need to be validated when we are not recording.  Mainly to do with the output stuff.
412 # 20030610 - 1.24- Moved the tunerNum variable into the config file: TunerNum
413 #                  Added --tuner-num option to dynamically set it.
414 # 20030614 - 1.25- I now require Video::ivtv 0.09 to make sure everyone is using the version that fixes the known
415 #                  reported segfault issues.
416 #                  Added freqtable "custom" support so that people using the new feature in ptune-ui.pl and have
417 #                  set their default frequency table to be "custom" will just work when they specify channel X, etc.
418 #                  I'm now sorting the command line input since otherwise I can't guarantee the order options get
419 #                  processed in, but even that is wrong.  I need to use Tie::IxHash, but that isn't standard.
420 # 20030626 - 1.26- Updated to cover the audio -> audio_bitmask changes that Video::ivtv 0.11 implemented to cover
421 #                  the ivtv_ioctl_codec structure changes.
422 #                  Implemented config file versioning so that I know when the Audio entry needs to be updated in case it
423 #                  comes back in a future version of the ivtv_ioctl_codec structure.
424 # 20030628 - 1.27- Adding --list-inputs and --list-standards to display the available inputs and video standards.
425 # 20030713 - 1.28- Added code to make sure the codec properties are proper when switching standard to PAL/SECAM.
426 #                  Added config options SetMSPMatrix, MSPInput, MSPOutput, MSPSleep to allow the user to specify if they
427 #                  want the msp matrix updated any time the Video Standard is changed and to specify what they want programmed.
428 #                  Bumping the config file version to 2 to account for the new options.
429 # 20030715 - 1.29- Adding the missing msp matrix reset code in the reset section.
430 #                  Adding codec checks to make sure that they are right for NTSC.
431 #                  Made it legal to specify the channel by itself without -c/--channel.
432
433
434 #use strict;
435 use Getopt::Long qw(:config no_ignore_case bundling);
436 use Fcntl;
437 use Video::Frequencies 0.03;
438 use Video::ivtv 0.12;
439 use Config::IniFiles;
440
441 my $version="1.29";
442 my $cfgVersion = "2";
443 my $cfgVersionStr = "_configVersion_"# hopefully unique [defaults] value to let me know what version the config file is.
444
445 my @capabilities = ();  # The cards capabilities
446
447 my %settings = (
448   Channel           =>  $ivtvrecch ,            # default to the ivtv default channel
449   RecordDuration    => $reclengthsec ,          # default to 59 minutes 50 seconds (in seconds) - This lets 2 back to back cron jobs work!
450   InputNum          => $capturedeviceinputnum ,      # TV-Tuner 0 on GV-MVP/RX $capturedeviceinputnum
451   InputName         => "$capturedeviceinputName",
452   OutputDirectory   => "$recfolderpath",
453   VideoDevice       => "$recdevice",
454   VideoWidth        => "720",   # 720x480-fullscreen NTSC
455   VideoHeight       => "480",
456   VideoStandard     => "NTSC"# NTSC, PAL or SECAM
457   VideoType         => "mpeg"# mpeg, yuv
458   Bitrate           => "$stdbitrate",
459   PeakBitrate       => "$peakbitrate"# peak bitrate
460   Aspect            => 2,
461   AudioBitmask      => 0x00e9,
462   BFrames           => 3,
463   DNRMode           => 0,
464   DNRSpatial        => 0,
465   DNRTemporal       => 0,
466   DNRType           => 0,
467   Framerate         => 0,
468   FramesPerGOP      => 15,
469   GOPClosure        => 1,
470   Pulldown          => 0,
471   StreamType        => 0,  # 10 = DVD format (almost)
472   OutputFileName    => "$outputfile",
473   FrequencyTable    => "$frequencyTable"# default to NTSC_CABLE mapping.
474   Frequency         => "", # user specified frequency.
475   ResetCardSettings => 1,
476   ConfigFileName    => "$ENV{HOME}/.ivtvrc",
477   UpdateConfigFile  => 0,
478   UseConfigFile     => 0,
479   UsingIvtvDriver   => 1,  # default to being able to use the ivtv "enhancements".
480   DontRecord        => 0,  # default to always recording data.
481   DirectoryFormatString => " ", # format string used to define the sub directory under OutputDirectory
482   DateTimeFormatString  => "+%Y%m%d-%H%M", # format string used to represent the date/time if the user wants it in their DirectoryFormatString
483   # define the Codec related min/max values
484   minBitrate        => 1,
485   maxBitrate        => 14500000,
486   minPeakBitrate    => 1500,
487   maxPeakBitrate    => 16000000,
488   # msp matrix settings
489   SetMSPMatrix      => 1,
490   MSPInput          => 3,
491   MSPOutput         => 1,
492   MSPSleep          => 2,  # number of seconds the card needs before we can set the msp matrix.
493   # other settings
494   Debug             => 0,#DEBUG
495   TunerNum          => 0,
496 );
497
498
499 print " $settings{InputNum} / $settings{InputName} /IVTVRECCH:$settings{Channel}/$recdevice  \n\n" if $settings{Debug};
500
501
502 my $result="";
503 my @profileNames=(); # list of user defined sections to work with in the config file.
504 my %configIni;      # config hash we tie to for Config::IniFiles.
505 my $ivtvObj = Video::ivtv->new();
506
507 # map the Settings/Config file parameter to the command line variable that specifies it.
508 my %mappings = (
509     "Channel"           => "c|channel",
510     "RecordDuration"    => "t|duration",
511     "InputNum"          => "i|inputnum",
512     "InputName"         => "I|inputname",
513     "OutputDirectory"   => "D|directory",
514     "VideoDevice"       => "d|input",
515     "VideoWidth"        => "W|width",
516     "VideoHeight"       => "H|height",
517     "VideoStandard"     => "s|standard",
518     "VideoType"         => "T|type",
519     "Bitrate"           => "b|bitrate",
520     "PeakBitrate"       => "B|peakbitrate",
521     "Aspect"            => "aspect",
522     "AudioBitmask"      => "audio-bitmask",
523     "BFrames"           => "bframes",
524     "DNRMode"           => "dnrmode",
525     "DNRSpatial"        => "dnrspatial",
526     "DNRTemporal"       => "dnrtemporal",
527     "DNRType"           => "dnrtype",
528     "Framerate"         => "framerate",
529     "FramesPerGOP"      => "framespergop",
530     "GOPClosure"        => "gopclosure",
531     "Pulldown"          => "pulldown",
532     "StreamType"        => "streamtype",
533     "OutputFileName"    => "o|output",
534     "FrequencyTable"    => "f|freqtable",
535     "Frequency"         => "F|frequency",
536     "ResetCardSettings" => "R|noreset",
537     "DirectoryFormatString" => "directory-format",
538     "DateTimeFormatString"  => "date-format",
539     "Debug"             => "debug",
540     "TunerNum"          => "tuner-num",
541     "SetMSPMatrix"      => "set-msp-matrix",
542     "MSPInput"          => "msp-input",
543     "MSPOutput"         => "msp-output",
544     "MSPSleep"          => "msp-sleep",
545     "OutputMPGFileName"   => "outputmpgfilename",
546   );
547
548 my %codecMappings = (
549     "Aspect"       => "aspect",
550     "AudioBitmask" => "audio_bitmask",
551     "BFrames"      => "bframes",
552     "Bitrate"      => "bitrate",
553     "PeakBitrate"  => "bitrate_peak",
554     "DNRMode"      => "dnr_mode",
555     "DNRSpatial"   => "dnr_spatial",
556     "DNRTemporal"  => "dnr_temporal",
557     "DNRType"      => "dnr_type",
558     "Framerate"    => "framerate",
559     "FramesPerGOP" => "framespergop",
560     "GOPClosure"   => "gop_closure",
561     "Pulldown"     => "pulldown",
562     "StreamType"   => "stream_type",
563   );
564
565 # check for devfs support
566 if ( -e "/dev/.devfsd" )
567 {
568   $settings{VideoDevice} = "/dev/v4l/video0";
569 }
570
571 ## check for the config file
572 #if (-f $settings{ConfigFileName})
573 #{
574 #  $settings{UseConfigFile} = 1;
575 #
576 #  # tie to it.
577 #  tie %configIni, 'Config::IniFiles', (-file => $settings{ConfigFileName}) or die "Error: Opening config file '$settings{ConfigFileName}' failed! $!\n";
578 #
579 #  my $profile = "defaults";
580 #  if (exists $configIni{$profile})
581 #  {
582 #    my $saveFile = 0;
583 #    # check version of the config file.
584 #    if (!exists $configIni{$profile}{$cfgVersionStr})
585 #    {
586 #      print "Updating config file to version 1...\n";
587 #
588 #      # first version config file!  Update the Audio -> AudioBitmask entries.
589 #      $configIni{$profile}{$cfgVersionStr} = 1;
590 #
591 #      # find all entries that have Audio and move to AudioBitmask.
592 #      foreach my $p (keys %configIni)
593 #      {
594 #        if (exists $configIni{$p}{Audio})
595 #        {
596 #          $configIni{$p}{AudioBitmask} = $configIni{$p}{Audio};
597 #          delete $configIni{$p}{Audio};
598 #        }
599 #      }
600 #     
601 #      $saveFile = 1;  # signal we need to save the config changes.
602 #    }
603 #    if ($configIni{$profile}{$cfgVersionStr} != $cfgVersion)
604 #    {
605 #      # we need to upgrade
606 #      if ($configIni{$profile}{$cfgVersionStr} == 1)
607 #      {
608 #        print "Updating config file to version 2...\n";
609 #        # add the MSP Matrix related options.
610 #        $configIni{$profile}{SetMSPMatrix} = $settings{SetMSPMatrix};
611 #        $configIni{$profile}{MSPInput} = $settings{MSPInput};
612 #        $configIni{$profile}{MSPOutput} = $settings{MSPOutput};
613 #        $configIni{$profile}{MSPSleep} = $settings{MSPSleep};
614 #        $configIni{$profile}{$cfgVersionStr} = 2;
615 #        $saveFile = 1;
616 #      }
617 #    }
618 #
619 #    if ($saveFile)
620 #    {
621 #      # now save the updated config file before we continue.
622 #      tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed!  $!\n";
623 #    }
624 #
625 #    # update the defaults stored.
626 #    foreach my $arg (keys %mappings)
627 #    {
628 #      if (exists $configIni{$profile}{$arg})
629 #      {
630 #        $settings{$arg} = $configIni{$profile}{$arg};
631 #        print "settings{$arg} = '" . $settings{$arg} . "'\n";
632 #      }
633 #    }
634 #  }
635 #  else
636 #  {
637 #    print "Warning: config file '$settings{ConfigFileName}' exists but does not have the\n[$profile] section!  Use -S to create it without specifying -P.\n\n";
638 #  }
639 #}
640 #else  # create the config file
641 #{
642 #  print "Auto Creating config file $settings{ConfigFileName}...\n";
643 #  my $profile = "defaults";
644 #
645 #  # we have to create the config file and tie to it.
646 #  tie %configIni, 'Config::IniFiles', () or die "Error: Initializing config file '$settings{ConfigFileName}' failed! $!\n";
647 #
648 #  # now set the name to work with.
649 #  tied(%configIni)->SetFileName($settings{ConfigFileName}) or die "Error: Setting config file to '$settings{ConfigFileName}' failed! $!\n";
650 #
651 #  $configIni{$profile} = {};  # make sure the section exists.
652 #
653 #  foreach my $arg (keys %mappings)
654 #  {
655 #    $configIni{$profile}{$arg} = $settings{$arg};
656 #    print "configIni{$profile}{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug};
657 #  }
658 #
659 #  # set the config file version
660 #  $configIni{$profile}{$cfgVersionStr} = $cfgVersion;
661 #
662 #  # write the config file out.
663 #  tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed!  $!\n";
664 #}
665
666 # build up the "custom" frequency table
667 my %customMap = ();
668 foreach my $profileName (keys %configIni)
669 {
670   next if $profileName =~ /^(defaults)$/;
671
672   if (exists $configIni{$profileName}{Frequency})
673   {
674     $customMap{$profileName} = $configIni{$profileName}{Frequency};
675   }
676 }
677 $CHANLIST{custom} = \%customMap;
678
679 # enumerations
680 my @standards;
681 my %name2std;
682 my @inputs;
683 my %name2input;
684 my @codecInfo;        # stores the Codec Info
685 my @newCodecInfo;     # the version we mess with.
686 # Current settings (Input, Channel, Standard)
687 my $curinput;
688 my $curinputName;
689 my $std;
690 my $curstd = "???";
691 my $curStandard = 0;  # numeric representation.
692 my $curChannel = 0;
693 my $curFrequency = 0;
694
695 my $tuner;
696 my $err;
697 my $v4l2input;
698
699 my $tmpDirectoryStr = formatDirectoryString();
700 my $versionStr = "record-v4l2.pl $version for use with http://ivtv.sf.net/";
701 my $usageStr = <<"END_OF_USAGE";
702 $versionStr
703
704 Usage: record-v4l2.pl [--channel CHANNEL] [--duration TIME]
705        [--directory DIRECTORY] [--output OUTPUT]
706        [--directory-format FORMAT] [--date-format FORMAT]
707        [--input VIDEO_DEV][--width WIDTH --height HEIGHT]
708        [--standard STANDARD] [--type TYPE]
709        [--inputnum INPUT#] [--inputname INPUT NAME]
710        [--freqtable FREQENCY MAP] [--frequency FREQUENCY]
711        [--bitrate BITRATE] [--peakbitrate PEAK_BITRATE]
712        [--set-msp-matrix BOOL] [--msp-sleep SLEEP]
713        [--msp-input INPUT] [--msp-output OUTPUT]
714        [--profile PROFILE] [--list-freqtable] [--list-channels]
715        [--no-record] [--noreset] [--save] [--help] [--version]
716        [--aspect ASPECT] [--audio-bitmask AUDIO-BITMASK] [--bframes BFRAMES]
717        [--dnrmode DNRMODE] [--dnrspatial DNRSPATIAL]
718        [--dnrtemporal DNRTEMPORAL] [--dnrtype DNRTYPE]
719        [--framerate FRAMERATE] [--framespergop FRAMESPERGOP]
720        [--gopclosure GOPCLOSURE] [--pulldown PULLDOWN]
721        [--streamtype STREAMTYPE] [--debug]
722        [--tuner-num TUNERNUM]
723        [--list-inputs] [--list-standards] [CHANNEL]
724
725   -c/--channel CHANNEL: channel number to switch to
726       NOTE: You can also specify the channel by itself.
727             Ex.  record-v4l2.pl 73
728             would change to channel 73 using the default settings
729             or the settings from your ~/.ivtvrc config file.
730   -t/--duration TIME: number of seconds to record
731   -D/--directory DIRECTORY: Base directory to record into
732   --directory-format FORMAT: format string that specifies the
733        sub-directory to create under the base directory that
734        the output file will be created in.  This can be empty
735        to indicate no sub-directory should be created.
736
737        Available tokens are:
738          %d - date formatted by --date-format
739          %I - input name recorded from
740               Any white space in the name is converted to
741               underscores (_).  Ex. 'Tuner 0' => 'Tuner_0'
742
743          %c - channel or "freq-#" frequency
744
745   --date-format FORMAT: format string that specifies the
746        date format string to generate and substitute for
747        %d in the --directory-format string.
748
749        Available tokens:  see the date commands man page.
750          The string must start with a + (plus).
751
752   -o/--output OUTPUT: name of file to create
753   -d/--input VIDEO_DEV: video device to capture from
754   -W/--width WIDTH: width of screen (720 for NTSC fullscreen)
755   -H/--height HEIGHT: height of screen (480 for NTSC fullscreen)
756   -s/--standard STANDARD: NTSC, PAL or SECAM - video standard to record in
757   -T/--type TYPE: mpeg or yuv output
758   -i/--inputnum INPUT#:
759        The index number of the input you want to use (0 -> n-1)
760   -I/--inputname INPUT NAME: The name of the input you want to use.
761   -f/--freqtable FREQUENCY MAP: Specify the frequency mapping to use.
762   -F/--frequency FREQUENCY: Specify the frequency to tune to.
763                 ex. 517250 = NTSC Cable 73 (SCiFi)
764   --tuner-num TUNERNUM: Specify the tuner to use.
765   --set-msp-matrix BOOL: 1 - set the msp matrix after Video Standard changes
766                          0 - never set the msp matrix
767                          Uses the --msp-input and --msp-output options.
768   --msp-sleep SLEEP: number of seconds the card needs before we can program
769                      the msp matrix.
770   --msp-input INPUT: Specify the input parameter to program the msp matrix.
771                      Valid values are from 1 - 8.
772   --msp-output OUTPUT: Specify the output parameter to program the msp matrix.
773                        Valid values are from 0 - 3.
774   -L/--list-freqtable:
775        list all available frequency mappings that Video::Frequencies knows
776   --list-channels: lists all channels and their frequencies for the
777        specified frequency table being used.
778   --list-inputs: lists all inputs the v4l2 driver reports.
779   --list-standards: lists all Video Standards the v4l2 driver supports.
780   -R/--noreset: Do not Reset anything that was changed
781       (standard, channel, resolution, etc.)
782   --no-record: Do not create any directories, capture data or reset the card
783               back to original settings.  This is the ptune.pl mode.
784   -h/--help: display this help
785   -v/--version: display the version of this program
786   --debug: turns on debug output
787
788   Codec related options:
789   -b/--bitrate BITRATE: Specify the Bitrate to capture at
790   -B/--peakbitrate PEAK_BITRATE: Specify the Peak Bitrate to capture at
791   --aspect ASPECT: Specify the aspect value
792   --audio-bitmask AUDIO-BITMASK:  Specify the audio bitmask value
793   --bframes BFRAMES: Specify the bframes value
794   --dnrmode DNRMODE: Specify the dnr_mode value
795   --dnrspatial DNRSPATIAL: Specify the dnr_spatial value
796   --dnrtemporal DNRTEMPORAL: Specify the dnr_temporal value
797   --dnrtype DNRTYPE: Specify the dnr_type value
798   --framerate FRAMERATE: Specify the framerate value
799   --framespergop FRAMESPERGOP: Specify the framespergop value
800   --gopclosure GOPCLOSURE: Specify the gop_closure value
801   --pulldown PULLDOWN: Specify the pulldown value
802   --streamtype STREAMTYPE: Specify the stream_type value
803
804   Config file related options:
805   -P/--profile PROFILE: Override defaults and command line values with the
806               config entries in the section labeled [PROFILE] from the
807               config file $settings{ConfigFileName}.
808               Examples: -P NTSC-DVD, -P PAL-DVD, --profile MY-SETTINGS
809
810               You can specify this option multiple times and each successive
811               profile will overlay the defaults and any previous profiles.
812               You will not be able to create/update a profile if you do
813               specify multiple profiles.
814   -S/--save: save the current values as the defaults in
815       $settings{ConfigFileName}.
816       If -P/--profile PROFILE is specified, then those values that exist in
817       the specified profile will be updated.  If the profile doesn't exist,
818       then it will be created, but will have all possible config items
819       defined in it.  It will be your responsibility to hand check the
820       config file and remove any config items you do not want set for
821       that profile.
822       Any options specified on the command line will override options
823       defined in the config file.
824
825 Notes:
826   If you specify both -i/--inputnum and -I/--inputname then
827       -i/--inputnum will take precedence.
828
829   If you specify both -c/--channel and -F/--frequency then
830       -F/--frequency will take precedence.
831
832   If you use a Profile, it has the ability to override all command line
833     arguments, so check your Profile first if things seem to be ignored.
834
835 Defaults:
836  --duration $settings{RecordDuration} --input $settings{VideoDevice} --width $settings{VideoWidth} --height $settings{VideoHeight} --standard $settings{VideoStandard}
837  --type $settings{VideoType} --directory $settings{OutputDirectory} --output $settings{OutputFileName}
838  --directory-format "$settings{DirectoryFormatString}" --date-format "$settings{DateTimeFormatString}"
839  --inputnum $settings{InputNum} --inputname '$settings{InputName}' --freqtable $settings{FrequencyTable}
840  --set-msp-matrix $settings{SetMSPMatrix} --msp-sleep $settings{MSPSleep} --msp-input $settings{MSPInput} --msp-output $settings{MSPOutput}
841  --bitrate $settings{Bitrate} --peakbitrate $settings{PeakBitrate} --aspect $settings{Aspect} --audio-bitmask $settings{AudioBitmask} --bframes $settings{BFrames}
842  --dnrmode $settings{DNRMode} --dnrspatial $settings{DNRSpatial} --dnrtemporal $settings{DNRTemporal} --dnrtype $settings{DNRType}
843  --framerate $settings{Framerate} --framespergop $settings{FramesPerGOP} --gopclosure $settings{GOPClosure} --pulldown $settings{Pulldown} --streamtype $settings{StreamType}
844  --tuner-num $settings{TunerNum}
845
846  config file = '$settings{ConfigFileName}'
847
848  If Channel = $settings{Channel}, this would create:
849  $tmpDirectoryStr$settings{OutputFileName}
850
851  Note:  This script relies on Perl Modules: Video::Frequencies, Video::ivtv,
852  Config::IniFiles and Getopt::Long.
853 END_OF_USAGE
854
855 # handle user input here
856 my %opts;
857 #getopts('c:t:o:hd:W:H:s:T:D:vi:I:f:F:LRb:B:P:S', \%opts);
858 GetOptions(\%opts, "channel|c=s", "duration|t=i", "output|o=s", "help|h", "input|d=s", "width|W=i", "height|H=i", "standard|s=s",
859                    "type|T=s", "directory|D=s", "version|v", "inputnum|i=i", "inputname|I=s", "freqtable|f=s", "frequency|F=i", "list-freqtable|L",
860                    "noreset|R", "bitrate|b=i", "peakbitrate|B=i", "profile|P=s@", "save|S", "aspect=i", "audio-bitmask=s", "bframes=i", "dnrmode=i", "dnrspatial=i",
861                    "dnrtemporal=i", "dnrtype=i", "framerate=i", "framespergop=i", "gopclosure=i", "pulldown=i",
862                    "streamtype=i", "no-record", "directory-format=s", "date-format=s", "debug", "list-channels",
863                    "tuner-num=i", "list-inputs", "list-standards", "set-msp-matrix=i", "msp-input=i", "msp-output=i", "outputmpgfilename=s");
864 if (scalar keys %opts == 0 && @ARGV == 0)
865 {
866   usage(0, "");
867 }
868 foreach my $option (sort keys %opts)
869 {
870   my $found = 0;
871   foreach my $mapName (keys %mappings)
872   {
873     if ($option =~ /^($mappings{$mapName})$/)
874     {
875       $settings{$mapName} = $opts{$option};
876       $found = 1;
877       print "$mapName = '$opts{$option}'\n" if $settings{Debug};
878     }
879   }
880   if (!$found)
881   {
882     # handle the non-settings cases.
883     if ($option =~ /^(L|list-freqtable)$/)
884     {
885       my $errStr = "\nAvailable Frequency Mappings:\n";
886       foreach my $name (sort keys %CHANLIST)
887       {
888         $errStr .= "$name\n";
889       }
890       print "$versionStr\n$errStr";
891       exit 0;
892     }
893     elsif ($option eq "list-channels")
894     {
895       my $errStr = "\nAvailable Channels for $settings{FrequencyTable}:\n";
896       foreach my $name (sort { $a <=> $b } keys %{$CHANLIST{$settings{FrequencyTable}}})
897       {
898         $errStr .= "$name\t= $CHANLIST{$settings{FrequencyTable}}->{$name}\n";
899       }
900       print "$versionStr\n$errStr";
901       exit 0;
902     }
903     elsif ($option =~ /^(no-record)$/)
904     {
905       $settings{DontRecord} = 1;
906     }
907     elsif ($option =~ /^(S|save)$/)
908     {
909       $settings{UpdateConfigFile} = 1;
910     }
911     elsif ($option =~ /^(P|profile)$/)
912     {
913       @profileNames = @{$opts{$option}};
914     }
915     elsif ($option =~ /^(v|version)$/)
916     {
917       print "$versionStr\n";
918       exit 0;
919     }
920     elsif ($option =~ /^(h|help)$/)
921     {
922       usage(0, "");
923     }
924     elsif ($option =~ /^(list-inputs|list-standards)$/)
925     {
926       # do nothing for now since they will be handled later.
927     }
928
929     else
930     {
931       usage(1, "-$option is an unknown option!");
932     }
933   }
934 }
935
936 if (@profileNames)
937 {
938   # loop over all profiles the user specified.
939   foreach my $profileName (@profileNames)
940   {
941     print "profile = '$profileName'\n" if $settings{Debug};
942     # for now the profile can not be "defaults".
943     if ($profileName eq "defaults")
944     {
945       error(1, "Profile = '$profileName' is invalid!");
946     }
947     if (exists $configIni{$profileName})
948     {
949       # update defaults/override command line arguments that exist in this profile.
950       my $profileUpdating = (((exists $opts{S} || exists $opts{save}) && @profileNames == 1) ? 1 : 0);
951       my $profile = $profileName;
952
953       foreach my $arg (keys %mappings)
954       {
955         foreach my $option (split(/\|/, $mappings{$arg})) # handle the long/short command option versions
956         {
957           #print "arg = '$arg', option = '$option'\n" if $settings{Debug};
958           if (exists $configIni{$profile}{$arg} && !($profileUpdating && exists $opts{$option}))
959           {
960             $settings{$arg} = $configIni{$profile}{$arg};
961             print "settings{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug};
962             last;
963           }
964         }
965       }
966     }
967     else
968     {
969       if ($settings{UpdateConfigFile} && @profileNames == 1)
970       {
971         print "Warning:  Profile = '$profileName' will be created.\n" if ($settings{Debug});
972       }
973       else
974       {
975         error(1, "Profile = '$profileName' does not exist! You must specify -S/--save to create it.");
976       }
977     }
978   }
979 }
980
981 # verify input
982
983 if (@ARGV)
984 {
985   if (exists $opts{c} || exists $opts{channel})
986   {
987     print "Warning: ignoring channel argument and using '$ARGV[0]' instead.\n";
988   }
989   $settings{Channel} = $ARGV[0];
990 }
991
992 if (!$settings{DontRecord})
993 {
994   print "RecordDuration = $settings{RecordDuration}\n" if $settings{Debug};
995
996   if ($settings{VideoType} !~ /^(mpeg|yuv)$/)
997   {
998     error(1, "Video Type = '$settings{VideoType}' is invalid!");
999   }
1000   if ($settings{VideoType} eq "yuv")
1001   {
1002     # see if we need to change our defaults.
1003     if (!exists $opts{o} && !exists $opts{output})
1004     {
1005       $settings{OutputFileName} = "video.yuv";
1006     }
1007     if (!exists $opts{d} && !exists $opts{input})
1008     {
1009       if ( -e "/dev/.devfsd" )
1010       {
1011         $settings{VideoDevice} = "/dev/v4l/yuv0";
1012       }
1013       else
1014       {
1015         $settings{VideoDevice} = "/dev/yuv0";
1016       }
1017     }
1018   }
1019 }
1020
1021 if ( ! -c "$settings{VideoDevice}")
1022 {
1023   error(1, "Video Dev = '$settings{VideoDevice}' is invalid!  $!");
1024 }
1025
1026 # now that the video device has been semi validated, we can use it to lookup
1027 # the inputs, standards, etc. and use that for validating some of the following
1028 # pieces of user input.
1029 sysopen($tuner, $settings{VideoDevice}, O_RDWR) or die "Error unable to open '$settings{VideoDevice}': $!";
1030 my $tunerFD = fileno($tuner);
1031
1032 # get the current capabilities.
1033 @capabilities = $ivtvObj->getCapabilities($tunerFD);
1034 if (@capabilities != keys %{$ivtvObj->{capIndexes}})
1035 {
1036   error(1, "getCapabilities() failed!");
1037 }
1038 if ($capabilities[$ivtvObj->{capIndexes}{driver}] ne "ivtv")
1039 {
1040   $settings{UsingIvtvDriver} = 0;  # we can't use the ivtv "enhancements".
1041   print "Warning:  V4l2 driver = '$capabilities[$ivtvObj->{capIndexes}{driver}]' does not support the ivtv \"enhancements\"!\n";
1042   print "          All codec related options will be ignored.\n\n";
1043 }
1044
1045 my $i;
1046
1047 # get the current video standard
1048 $std = $ivtvObj->getStandard($tunerFD);
1049 if ($std > 0)
1050 {
1051   printf("Standard: 0x%08x\n",$std) if ($settings{Debug});
1052 }
1053 else
1054 {
1055   die "Error: getStandard() failed!\n";
1056 }
1057
1058 # get the current input
1059 $curinput = $ivtvObj->getInput($tunerFD);
1060 if ($curinput < 0)
1061 {
1062   die "Error: getInput() failed!\n";
1063 }
1064 printf("Input: 0x%08x\n",$curinput) if ($settings{Debug});
1065
1066 my $done=0;
1067 # Standards
1068 for ($i=0; !$done; ++$i)
1069 {
1070   my($index,$std_id,$name,$frameperiod_n,$frameperiod_d,$framelines) = $ivtvObj->enumerateStandard($tunerFD, $i);
1071   if ($index == -1)
1072   {
1073     $done = 1;
1074   }
1075   else
1076   {
1077     printf("%d 0x%08x %s %d/%d %d\n",$index,$std_id,$name,$frameperiod_n,$frameperiod_d,$framelines) if ($settings{Debug});
1078     push @standards, [($name,$std_id)];
1079     $name2std{$name} = $std_id;
1080     if( (($std_id & $std) == $std))
1081     {
1082       $curstd = $name;
1083       $curStandard = $std;
1084     }
1085   }
1086 }
1087
1088 if (exists $opts{'list-standards'})
1089 {
1090   print "$versionStr\n";
1091   print "Available Video Standards:\n";
1092   foreach my $standard (@standards)
1093   {
1094     print "$standard->[0]\n";
1095   }
1096   exit 0;
1097 }
1098
1099 $done=0;
1100 # Inputs
1101 for ($i=0; !$done; ++$i)
1102 {
1103   my($index,$name,$type,$audioset,$tuner,$std,$status) = $ivtvObj->enumerateInput($tunerFD, $i);
1104   if ($index == -1)
1105   {
1106     $done = 1;
1107   }
1108   else
1109   {
1110     push @inputs, $name;
1111     $name2input{$name} = $index;
1112   }
1113 }
1114 $curinputName = $inputs[$curinput];
1115
1116 if (exists $opts{'list-inputs'})
1117 {
1118   print "$versionStr\n";
1119   print "Available Inputs:\n";
1120   my $counter = 0;
1121   foreach my $input (@inputs)
1122   {
1123     print "$counter: $input\n";
1124     $counter++;
1125   }
1126   exit 0;
1127 }
1128
1129 if ($settings{UsingIvtvDriver})
1130 {
1131   # get the current Codec Info
1132   @codecInfo = $ivtvObj->getCodecInfo($tunerFD);
1133   if (@codecInfo != keys %{$ivtvObj->{codecIndexes}})
1134   {
1135     error(1, "getCodecInfo() failed!");
1136   }
1137   @newCodecInfo = $ivtvObj->getCodecInfo($tunerFD);
1138   if (@newCodecInfo != keys %{$ivtvObj->{codecIndexes}})
1139   {
1140     error(1, "getCodecInfo() failed!");
1141   }
1142 }
1143
1144 # finish validating the user input.
1145
1146 if (!$settings{DontRecord})
1147 {
1148   if ($settings{RecordDuration} !~ /^(\d+)$/)
1149   {
1150     error(1, "Time = '$settings{RecordDuration}' is invalid!");
1151   }
1152
1153   if ( ! -d "$settings{OutputDirectory}")
1154   {
1155     error(1, "Directory = '$settings{OutputDirectory}' is invalid!  $!");
1156   }
1157
1158   # assume for now we are only generating mpeg files.
1159 #  if (($settings{VideoType} eq "mpeg" && $settings{OutputFileName} !~ /^.+\.mpg$/) || ($settings{VideoType} eq "yuv" && $settings{OutputFileName} !~ /^.+\.yuv$/))
1160 #  {
1161 #    error(1, "Output = '$settings{OutputFileName}' is invalid!");
1162 #  }
1163 #
1164   if ($settings{DateTimeFormatString} !~ /^(\+((\%.)|.)+)$/)
1165   {
1166     usage(1, "Date Format String = '$settings{DateTimeFormatString}' is invalid!");
1167   }
1168 }
1169
1170 if ($settings{VideoWidth} !~ /^(\d+)$/)
1171 {
1172   error(1, "Width = '$settings{VideoWidth}' is invalid!");
1173 }
1174
1175 if ($settings{VideoHeight} !~ /^(\d+)$/)
1176 {
1177   error(1, "Height = '$settings{VideoHeight}' is invalid!");
1178 }
1179
1180 if (!exists $name2std{$settings{VideoStandard}})
1181 {
1182   my $validStandards = join(", ", keys(%name2std));
1183   error(1, "Video Standard = '$settings{VideoStandard}' is invalid!\nValid Standards are: $validStandards");
1184 }
1185
1186 if (exists $opts{i} || exists $opts{inputnum})
1187 {
1188   if ($settings{InputNum} < 0 || $settings{InputNum} >= scalar(@inputs))
1189   {
1190     error(1, "Video Input = '$settings{InputNum}' is invalid!\nValid Inputs are from 0 - " . int(scalar(@inputs) - 1));
1191   }
1192   $settings{InputName} = $inputs[$settings{InputNum}];
1193 }
1194
1195 if ((exists $opts{I} || exists $opts{inputname}) && !(exists $opts{i} || exists $opts{inputnum}))
1196 {
1197   if (!exists $name2input{$settings{InputName}})
1198   {
1199     my $validInputs = join(", ", @inputs);
1200     error(1, "Video Input Name = '$settings{InputName}' is invalid!\nValid Input Names are: $validInputs");
1201   }
1202   $settings{InputNum} = $name2input{$settings{InputName}};
1203 }
1204
1205 if (!exists $CHANLIST{$settings{FrequencyTable}})
1206 {
1207   error(1, "Frequency Table = '$settings{FrequencyTable}' is invalid!");
1208 }
1209
1210 # only validate the channel if the input is a tuner.
1211 if ($inputs[$settings{InputNum}] =~ /Tuner/)
1212 {
1213   if ($settings{TunerNum} !~ /^(\d)$/)
1214   {
1215     error(1, "TunerNum = '$settings{TunerNum}' is invalid!");
1216   }
1217   if (exists $opts{F} || exists $opts{frequency} || $settings{Frequency}) # the user may have specified a Frequency in their config file
1218   {
1219     if ($settings{Frequency} !~ /^(\d+)$/)
1220     {
1221       error(1, "Frequency = '$settings{Frequency}' is invalid!");
1222     }
1223     $settings{Channel} = "freq-$settings{Frequency}"# make sure we output the channel part.
1224   }
1225   # now verify that the channel exists in the frequency table!
1226   else
1227   {
1228     if (!$settings{Channel})
1229     {
1230       error(1, "channel = '$settings{Channel}' is invalid!");
1231     }
1232     # first verify the freqency table is appropriate for the standard (NTSC, PAL, SECAM),
1233     # unless they specified the frequency to tune to.
1234     if ($settings{FrequencyTable} !~ /^(custom|$settings{VideoStandard})/i)
1235     {
1236       error(1, "You specified Video Standard '$settings{VideoStandard}' which is incompatible with Frequency Table '$settings{FrequencyTable}'!");
1237     }
1238     if (!exists $CHANLIST{$settings{FrequencyTable}}->{$settings{Channel}})
1239     {
1240       error(1, "Channel = '$settings{Channel}' does not exist in Frequency Table '$settings{FrequencyTable}'!");
1241     }
1242   }
1243
1244   # get the current channel/frequency value.
1245   my $Frequency;
1246   if(($Frequency = $ivtvObj->getFrequency($tunerFD, $settings{TunerNum})) >= 0)
1247   {
1248     my $freq = ($Frequency * 1000) / 16;
1249     print "freq = $freq\n" if ($settings{Debug});
1250     # find the associated channel.
1251     if ((!exists $opts{F} && !exists $opts{frequency} && !$settings{Frequency}) && ($curstd eq $settings{VideoStandard}) )
1252     {
1253       foreach my $chan (keys %{$CHANLIST{$settings{FrequencyTable}}})
1254       {
1255         if ($CHANLIST{$settings{FrequencyTable}}->{$chan} == $freq)
1256         {
1257           $curChannel = $chan;
1258         }
1259       }
1260       print "curChannel = $curChannel\n" if ($settings{Debug});
1261     }
1262     else
1263     {
1264       $curFrequency = $freq;
1265     }
1266   }
1267   else
1268   {
1269     die "Error: getFrequency() failed!\n";
1270   }
1271 }
1272 else
1273 {
1274   # set the channel = "" so we know to ignore it.
1275   $settings{Channel} = "";
1276 }
1277
1278 if ($settings{UsingIvtvDriver})
1279 {
1280   # validate the Codec related stuff.
1281   if ($settings{Bitrate} < $settings{minBitrate} || $settings{Bitrate} > $settings{maxBitrate})
1282   {
1283     error(1, "Bitrate = '$settings{Bitrate}' is invalid!");
1284   }
1285   if ($settings{PeakBitrate} <= $settings{Bitrate})
1286   {
1287     error(1, "PeakBitrate can not be less than or equal to Bitrate!");
1288   }
1289   elsif ($settings{PeakBitrate} < $settings{minPeakBitrate} || $settings{PeakBitrate} > $settings{maxPeakBitrate})
1290   {
1291     error(1, "PeakBitrate = '$settings{PeakBitrate}' is invalid!");
1292   }
1293
1294   if ($settings{VideoStandard} !~ /^(NTSC)/)
1295   {
1296     my $warn = 0;
1297     if ($settings{Framerate} == 0)
1298     {
1299       $settings{Framerate} = 1;
1300       $warn = 1;
1301     }
1302     if ($settings{FramesPerGOP} == 15)
1303     {
1304       $settings{FramesPerGOP} = 12;
1305       $warn = 1;
1306     }
1307     if ($warn)
1308     {
1309       print "Warning:  Setting Framerate/FramesPerGOP to PAL settings for Video Standard '$settings{VideoStandard}'!\n\nYou should either specify on the command line or in the ~/.ivtvrc config file.\n";
1310     }
1311   }
1312   elsif ($settings{VideoStandard} =~ /^(NTSC)/)
1313   {
1314     my $warn = 0;
1315     if ($settings{Framerate} == 1)
1316     {
1317       $settings{Framerate} = 0;
1318       $warn = 1;
1319     }
1320     if ($settings{FramesPerGOP} == 12)
1321     {
1322       $settings{FramesPerGOP} = 15;
1323       $warn = 1;
1324     }
1325     if ($warn)
1326     {
1327       print "Warning:  Setting Framerate/FramesPerGOP to NTSC settings for Video Standard '$settings{VideoStandard}'!\n\nYou should either specify on the command line or in the ~/.ivtvrc config file.\n";
1328     }
1329   }
1330
1331   if ($settings{SetMSPMatrix} !~ /^(0|1)$/)
1332   {
1333     error(1, "SetMSPMatrix = '$settings{SetMSPMatrix}' is invalid!  It can only be 0 or 1.");
1334   }
1335   if ($settings{MSPInput} < 1 || $settings{MSPInput} > 8)
1336   {
1337     error(1, "MSPInput = '$settings{MSPInput}' is invalid!  It can only be 1 - 8.");
1338   }
1339   if ($settings{MSPOutput} < 0 || $settings{MSPOutput} > 3)
1340   {
1341     error(1, "MSPOutput = '$settings{MSPOutput}' is invalid!  It can only be 0 - 3.");
1342   }
1343 }
1344
1345 # update the config file if the user wants us to.
1346 if ($settings{UpdateConfigFile})
1347 {
1348   my $profile;
1349   if (@profileNames > 1)
1350   {
1351     print "Warning:  Not updating config file as you have more than 1 profile specified!\n";
1352   }
1353   elsif (@profileNames == 1)
1354   {
1355     $profile = $profileNames[0];
1356   }
1357   else
1358   {
1359     $profile = "defaults";
1360   }
1361   if ($profile)
1362   {
1363     my $createProfile = (exists $configIni{$profile} ? 0 : 1);
1364     print "Creating Profile = '$profile': $createProfile\n" if ($settings{Debug});
1365
1366     if (!$settings{UseConfigFile})
1367     {
1368       # we have to create the config file and tie to it.
1369       tie %configIni, 'Config::IniFiles', () or die "Error: Initializing config file '$settings{ConfigFileName}' failed! $!\n";
1370
1371       # now set the name to work with.
1372       tied(%configIni)->SetFileName($settings{ConfigFileName}) or die "Error: Setting config file to '$settings{ConfigFileName}' failed! $!\n";
1373
1374       $configIni{$profile} = {};  # make sure the section exists.
1375     }
1376
1377     foreach my $arg (keys %mappings)
1378     {
1379       foreach my $option (split(/\|/, $mappings{$arg})) # handle the long/short command option versions
1380       {
1381         if (exists $configIni{$profile}{$arg} || $createProfile || exists $opts{$option})
1382         {
1383           $configIni{$profile}{$arg} = $settings{$arg};
1384           print "configIni{$profile}{$arg} = '" . $settings{$arg} . "'\n" if $settings{Debug};
1385           last;
1386         }
1387       }
1388     }
1389
1390     # write the config file out.
1391     tied(%configIni)->RewriteConfig or die "Error: Writing config file '$settings{ConfigFileName}' failed!  $!\n";
1392   }
1393 }
1394
1395 # this hash keeps track of those values I have to set back.
1396 my %changedSettings = (
1397     resolution => 0,
1398     standard => 0,
1399     VideoType => 0,
1400     InputNum => 0,
1401     Channel => 0,
1402     Frequency => 0,
1403     codec => 0,
1404     );
1405
1406 my $directoryName;
1407 if (!$settings{DontRecord})
1408 {
1409   # make directory
1410   #$directoryName = formatDirectoryString();
1411   #$result=`mkdir -p $directoryName`;
1412         $directoryName = $settings{DirectoryFormatString};
1413 }
1414
1415 # change the channel
1416 if ($inputs[$settings{InputNum}] =~ /Tuner/)
1417 {
1418   if (exists $opts{F} || exists $opts{frequency} || $settings{Frequency})
1419   {
1420     if ($settings{Frequency} != $curFrequency)
1421     {
1422       $changedSettings{Frequency} = 1;
1423       tuneFrequency($settings{Frequency});
1424     }
1425   }
1426   else
1427   {
1428     if ($curstd ne $settings{VideoStandard})
1429     {
1430       # we have to set the channel regardless.
1431       # but we want to tune back to the previous frequency.
1432       $changedSettings{Frequency} = 1;
1433       changeChannel($settings{Channel});
1434     }
1435     elsif ($settings{Channel} ne $curChannel)
1436     {
1437       # otherwise we just changeChannel and restore the previous channel.
1438       $changedSettings{Channel} = 1;
1439       changeChannel($settings{Channel});
1440     }
1441   }
1442 }
1443
1444 # set the video standard
1445 if ($settings{VideoStandard} ne $curstd)
1446 {
1447   $changedSettings{standard} = 1;
1448   change_standard();
1449
1450   # see if we have to re-program the msp matrix
1451   if ($settings{UsingIvtvDriver})
1452   {
1453     if ($settings{SetMSPMatrix})
1454     {
1455       print "Setting msp matrix: input = $settings{MSPInput}, output = $settings{MSPOutput}\n" if $settings{Debug};
1456       sleep ($settings{MSPSleep});  # sleep for 2 seconds to let card settle down.
1457       $result = $ivtvObj->mspMatrixSet($tunerFD, $settings{MSPInput}, $settings{MSPOutput});
1458       if (not defined $result)
1459       {
1460         die "Error calling mspMatrixSet!\n";
1461       }
1462       if (!$result)
1463       {
1464         die "Error in mspMatrixSet ioctl call!\n";
1465       }
1466     }
1467   }
1468 }
1469
1470 # set the input
1471 if ($settings{InputNum} != $curinput || $settings{InputName} ne $curinputName)
1472 {
1473   $changedSettings{InputNum} = 1;
1474   if (!(exists $opts{i} || exists $opts{inputnum} || exists $opts{I} || exists $opts{inputname}))  # our defaults are different than the current values!
1475   {
1476    ## print "Warning:  Changing input from $curinputName to $settings{InputName}\n";
1477    &writelog("tvrecording:  Changing input from $curinputName to $settings{InputName}");
1478   }
1479   change_input();
1480 }
1481
1482 # set the capture type
1483
1484 # store the current width,height so we can restore afterwards
1485 my ($oldWidth, $oldHeight) = $ivtvObj->getResolution($tunerFD);
1486 print "oldWidth = '$oldWidth', oldHeight = '$oldHeight'\n" if ($settings{Debug});
1487
1488 if ($settings{VideoWidth} != $oldWidth || $settings{VideoHeight} != $oldHeight)
1489 {
1490   $changedSettings{resolution} = 1;
1491 }
1492
1493 # specify the width,height to capture
1494 if ($changedSettings{resolution})
1495 {
1496   $result = $ivtvObj->setResolution($tunerFD, $settings{VideoWidth}, $settings{VideoHeight});
1497   if (not defined $result)
1498   {
1499     die "Error calling setResolution!\n";
1500   }
1501   if (!$result)
1502   {
1503     die "Error in setResolution ioctl call!\n";
1504   }
1505 }
1506
1507 if ($settings{UsingIvtvDriver})
1508 {
1509   # specify the codec options to capture mpeg's at.
1510   foreach my $codecName (keys %codecMappings)
1511   {
1512     my $codecIndex = $ivtvObj->{codecIndexes}{$codecMappings{$codecName}};
1513     if ($codecInfo[$codecIndex] != $settings{$codecName})
1514     {
1515       $changedSettings{codec} = 1;
1516       $newCodecInfo[$codecIndex] = $settings{$codecName};
1517       print "new $codecName = '$settings{$codecName}', old $codecName = '$codecInfo[$codecIndex]'\n" if $settings{Debug};
1518     }
1519   }
1520 }
1521
1522 if ($changedSettings{codec})
1523 {
1524   $result = $ivtvObj->setCodecInfo($tunerFD, @newCodecInfo);
1525   if (!$result)
1526   {
1527     die "Error calling setCodecInfo()!\n";
1528   }
1529 }
1530
1531 if (!$settings{DontRecord})
1532 {
1533   # capture the video/audio to video.mpg
1534   #print "directoryName:$directoryName, RecordDuration:$settings{RecordDuration},OutputFileName:$settings{OutputFileName}:tuner:$tuner ,OutputMPGFileName:$settings{OutputMPGFileName}  \n";
1535   #directoryName:, RecordDuration:60,OutputFileName:/tv/JOAX-20040615-1411-000.MPG:tuner:GLOB(0x8224838) ,OutputMPGFileName: 
1536   captureVideo(directoryName => $directoryName, RecordDuration => $settings{RecordDuration},
1537               OutputFileName => $settings{OutputFileName}, tuner => $tuner ,OutputMPGFileName => $settings{OutputMPGFileName});
1538 }
1539
1540 if ($settings{ResetCardSettings} && !$settings{DontRecord})
1541 {
1542   # restore Codec values
1543   if ($changedSettings{codec})
1544   {
1545     $result = $ivtvObj->setCodecInfo($tunerFD, @codecInfo);
1546     if (!$result)
1547     {
1548       die "Error calling setCodecInfo()!\n";
1549     }
1550   }
1551
1552   # restore the previous width,height settings
1553   if ($changedSettings{resolution})
1554   {
1555     $result = $ivtvObj->setResolution($tunerFD, $oldWidth, $oldHeight);
1556     if (not defined $result)
1557     {
1558       die "Error calling setResolution!\n";
1559     }
1560     if (!$result)
1561     {
1562       die "Error in setResolution ioctl call!\n";
1563     }
1564   }
1565
1566   # restore the previous input setting
1567   if ($changedSettings{InputNum})
1568   {
1569     # reset back to the old input name
1570     $settings{InputName} = $curinputName;
1571     change_input();
1572   }
1573
1574   # restore the previous video standard
1575   if ($changedSettings{standard})
1576   {
1577     $settings{VideoStandard} = $curstd;
1578     change_standard();
1579
1580     # see if we have to re-program the msp matrix
1581     if ($settings{UsingIvtvDriver})
1582     {
1583       if ($settings{SetMSPMatrix})
1584       {
1585         print "Setting msp matrix: input = $settings{MSPInput}, output = $settings{MSPOutput}\n" if $settings{Debug};
1586         sleep ($settings{MSPSleep});  # sleep for 2 seconds to let card settle down.
1587         $result = $ivtvObj->mspMatrixSet($tunerFD, $settings{MSPInput}, $settings{MSPOutput});
1588         if (not defined $result)
1589         {
1590           die "Error calling mspMatrixSet!\n";
1591         }
1592         if (!$result)
1593         {
1594           die "Error in mspMatrixSet ioctl call!\n";
1595         }
1596       }
1597     }
1598   }
1599
1600   # restore the previous channel
1601   if ($changedSettings{Channel})
1602   {
1603     changeChannel($curChannel);
1604   }
1605   if ($changedSettings{Frequency})
1606   {
1607     tuneFrequency($curFrequency);
1608   }
1609 }
1610
1611 # close the tuner device
1612 close($tuner);
1613
1614
1615 exit 0;
1616
1617 # usage(returnValue, ErrorString)
1618 # returnValue = 1 or 0
1619 # ErrorString = message you want to tell the user, but only if returnValue = 1.
1620 sub usage
1621 {
1622   my $errorCode = shift;
1623   my $error = shift;
1624
1625   print $usageStr;
1626   print "\nError:  $error\n" if ($errorCode == 1);
1627   print "$error\n" if ($errorCode == 2);
1628
1629   exit $errorCode;
1630 }
1631
1632 # error(returnValue, ErrorString)
1633 # returnValue = 1 or 0
1634 # ErrorString = message you want to tell the user.
1635 sub error
1636 {
1637   my $errorCode = shift;
1638   my $error = shift;
1639
1640   print "$versionStr";
1641   print "\nError:  $error\n";
1642
1643   exit $errorCode;
1644 }
1645
1646 # changes the input to $settings{InputNum} as long as it isn't = $curinput
1647 sub change_input {
1648   my $preinput = $name2input{$settings{InputName}};
1649   if($preinput != $curinput)
1650   {
1651     $curinput = $preinput;
1652     print "input now $settings{InputName}, #$preinput\n" if ($settings{Debug});
1653     my $result = $ivtvObj->setInput($tunerFD, $preinput);
1654     if (!$result)
1655     {
1656       die "Error:  setInput($preinput) failed!\n";
1657     }
1658   }
1659 }
1660
1661 # changes the video standard to $settings{VideoStandard} as long as it isn't = $curstd
1662 sub change_standard {
1663   my $standard = $name2std{$settings{VideoStandard}};
1664   if($standard != $curStandard)
1665   {
1666     $curStandard = $standard;
1667     print "standard now $settings{VideoStandard}, #$standard\n" if ($settings{Debug});
1668     my $result = $ivtvObj->setStandard($tunerFD, $standard);
1669     if (!$result)
1670     {
1671       die "Error:  setStandard($standard) failed!\n";
1672     }
1673   }
1674 }
1675
1676 # changes the channel
1677 # takes the channel to change
1678 sub changeChannel
1679 {
1680   my $ch = shift;
1681   my $freq = $CHANLIST{$settings{FrequencyTable}}->{$ch};
1682   my $driverf = ($freq * 16)/1000;
1683
1684   print "Ch.$ch: $freq $driverf\n" if ($settings{Debug});
1685
1686   if (!$ivtvObj->setFrequency($tunerFD, $settings{TunerNum}, $driverf))
1687   {
1688     die "Error:  changeChannel($ch) failed!\n";
1689   }
1690 }
1691
1692 # tunes to the specified frequency
1693 # takes the frequency to tune to
1694 sub tuneFrequency
1695 {
1696   my $freq = shift;
1697   my $driverf = ($freq * 16)/1000;
1698
1699   print "freq: $freq $driverf\n" if ($settings{Debug});
1700
1701   if (!$ivtvObj->setFrequency($tunerFD, $settings{TunerNum}, $driverf))
1702   {
1703     die "Error:  tuneFrequency($freq) failed!\n";
1704   }
1705 }
1706
1707 my $done = 0;
1708
1709 sub catch_alarm {
1710   $done = 1;
1711 }
1712 sub get_next_file_name
1713 {
1714
1715   my $file_name = shift(@_);
1716   $file_name =~ m/^(.+?)\-(\d{4})(\d{2})(\d{2})\-(\d{2})(\d{2})\-(\d{3})\.(.+?)$/;
1717  
1718   my $station = $1;
1719   my $year    = $2;
1720   my $month   = $3;
1721   my $day     = $4;
1722   my $hour    = $5;
1723   my $min     = $6;
1724   my $seq     = $7;
1725   my $ext     = $8;
1726   $seq++;
1727   my $new_file_name = sprintf("%s-%04d%02d%02d-%02d%02d-%03d.%s",
1728                             $station,$year,$month,$day,$hour,$min,$seq,$ext);
1729   return $new_file_name
1730 }
1731
1732 # does the actual video capturing work.
1733 # takes directoryName, RecordDuration, OutputFileName, tuner
1734 sub captureVideo
1735 {
1736   my %args = ( @_ );
1737   my $directoryName = $args{directoryName};
1738   my $RecordDuration = $args{RecordDuration};
1739   my $OutputFileName = $args{OutputFileName};
1740   my $tuner = $args{tuner};
1741   my $fname = "$directoryName/$OutputFileName";
1742 #    "OutputMPGFileName"   => "outputmpgfilename",
1743 #  my $OutputFileName = $args{OutputMPGFileName};
1744   my $OutputFileName = $args{OutputFileName};
1745 #  my $fname = "$directoryName/$OutputFileName";
1746   my $fname = $args{OutputFileName};
1747  
1748
1749   # setup global variables, signal handlers, etc.
1750
1751   $SIG{ALRM} = \&catch_alarm;
1752   $SIG{INT}  = \&catch_alarm;  # handle Ctrl-C
1753
1754   # turn off file buffering.
1755   #$|=1;
1756
1757   # open the file for writing.
1758
1759
1760
1761   sysopen(OUTPUT, "$fname", O_CREAT | O_WRONLY | O_LARGEFILE) or die "Error creating file '$fname': $!\n";
1762
1763   alarm($RecordDuration);
1764   my $buf = "";
1765   my $len = 0;
1766   while (!$done && read($tuner, $buf, 16384))
1767   {
1768     $len += length($buf);
1769 #    if ($len >= $max_file_size )
1770 #    {
1771 #       close(OUTPUT);
1772 #       $OutputFileName = get_next_file_name($OutputFileName);
1773 ##       $fname = "$directoryName/$OutputFileName";
1774 #       $fname = "$OutputFileName";
1775 #          &writelog("tvrecording switch next clip.$fname");
1776 #       sysopen(OUTPUT, "$fname", O_CREAT | O_WRONLY | O_LARGEFILE)
1777 #                       or die "Error creating file '$fname': $!\n";
1778 #       $len = 0;
1779 #    }
1780
1781     # read from the device and write to the file.
1782     print OUTPUT $buf;
1783   }
1784
1785   # close the file
1786   close(OUTPUT);
1787
1788   #$|=0;  # turn file buffering back on.
1789 }
1790
1791 # returns the formatted directory string
1792 sub formatDirectoryString
1793 {
1794   my $temp = $settings{DirectoryFormatString};
1795   my $result = $settings{OutputDirectory};
1796   my %lookupTable = (
1797     "d" => `/bin/date "$settings{DateTimeFormatString}"`,
1798     "I" => $settings{InputName},
1799     "c" => $settings{Channel},
1800   );
1801
1802   # fixup the InputName value
1803   $lookupTable{I} =~ s/\s/_/g;
1804   # cleanup the trailing slash on the date
1805   chomp $lookupTable{d};
1806
1807   foreach my $option ("d", "I", "c")
1808   {
1809     $temp =~ s/\%$option/$lookupTable{$option}/g;
1810   }
1811
1812   $result .= "/" . ($temp ? "$temp/" : "");
1813
1814   return $result;
1815 }
1816
1817
1818
1819
1820
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。
track feed