root/trunk/install/perl/tvrecording.pl

リビジョン 29, 59.6 kB (コミッタ: sorshi, コミット時期: 18 年 前)

時間計算間違って録画終了が十秒程度早くなりすぎていたのを修正

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