root/trunk/install/perl/tvrecording.pl

リビジョン 79, 59.7 kB (コミッタ: sorshi, コミット時期: 16 年 前)

tvrecording.pl:
 foltia簡易BBSで指摘されたXML解析の正規表現修正。
getxml2db.pl:
 foltia簡易BBSで指摘されたログ出力項目の修正。

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