root/trunk/install/perl/tvrecording.pl

リビジョン 1, 59.1 kB (コミッタ: jplcom, コミット時期: 17 年 前)

initial import

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