File dvsource-firewire-next.pl of Package dvswitch-git

152
 
1
#! /usr/bin/perl -w
2
# dvsource-firewire_jw.pl -- a rewrite of the firewire grabber.
3
# The original dvsource-firewire suffers from the following issues:
4
# if we have both /dev/fw0 and /dev/fw1, it takes the first one, even if the 
5
#  other one is only functional.
6
#
7
# (C) 2012, jw@suse.de, distribute under GPL-2.0+ or ask.
8
# 2012-10-14 -- V0.1 initial draft.
9
# 2012-10-16 -- V0.2 skip empty units
10
#
11
#############
12
## Requires: dvgrab
13
#
14
# Improvement: 
15
# check all cat /sys/bus/firewire/devices/*/guid
16
# and ignore those with 0x0000000000000000
17
# and ignore those with empty /sys/bus/firewire/devices/*/units
18
19
use strict;
20
use Data::Dumper;
21
use File::stat;
22
use File::Glob;
23
use Getopt::Long qw(:config no_ignore_case);
24
use Pod::Usage;
25
26
my $version = '0.2';
27
my $a_chan = undef;
28
my $a_name = undef;
29
my $retry_connect = 0;
30
my $host = undef;
31
my $port = undef;
32
my $tally = undef;
33
my $verbose = 0;
34
my $help = undef;
35
my $dvgrab = 'dvgrab';
36
my $dvgrab_opts = '-noavc';
37
my $ignore_missing_units = 0;
38
39
sub get_ps();
40
41
GetOptions(
42
    "retry|R"   => \$retry_connect,
43
    "verbose|v+"    => \$verbose,
44
    "port|p=s"  => \$port,
45
    "host|h=s"  => \$host,
46
    "tally|t"   => \$tally,
47
    "ignore-units|u" => \$ignore_missing_units,
48
    "help|?"    => \$help,
49
) or $help++;
50
51
pod2usage(-verbose => 1, -msg => qq{
52
dvsource-firewire_jw.pl V$version
53
54
55
$0 [OPTIONS]
56
57
Start a dvsource on the next available firewire device. Dead devices (without guid) are skipped,
58
devices that are in use (guid appears in /proc/*/cmdline) are also skipped.
59
Returns nonzero if no usable devices were found.
60
61
Valid options are:
62
 -v Print more information at startup.
63
64
 -R, --retry    
65
    Keep retrying to connect, in case DVswitch is not yet listening.
66
67
 -h, --host=HOST
68
 -p, --port=PORT
69
    Specify the network address on which DVswitch is listening.  The
70
    host address may be specified by name or as an IPv4 or IPv6 literal.
71
72
 -t, --tally
73
    Print notices of activation and deactivation in the  mixer,  for
74
    use with a tally light.  These will take the form "TALLY: on" or
75
    "TALLY: off".
76
77
}) if $help;
78
79
opendir DIR, "/sys/bus/firewire/devices/" or die "no /sys/bus/firewire/devices/: $!";
80
my @fw = grep { !/^\./ } readdir DIR;
81
closedir DIR;
82
my %fw = map { $_ => { guid => undef } } @fw;
83
my @good;
84
for my $fw (sort @fw)
85
  {
86
    if (open IN, '<', "/sys/bus/firewire/devices/$fw/guid")
87
      {
88
        my $guid = <IN> || '';
89
        chomp $guid;
90
        $fw{$fw}{guid} = $guid;
91
        close IN;
92
93
        if (open IN, '<', "/sys/bus/firewire/devices/$fw/units")
94
          {
95
        # expect 0x00a02d:0x010001
96
            my $units = <IN> || '';
97
            chomp $units;
98
            $fw{$fw}{units} = $units;
99
            close IN;
100
        $units = '0x0:0x0' if $ignore_missing_units;
101
102
            if (($guid =~ m{^0x[\da-f]*[1-9a-f][\da-f]*$}) and
103
            ($units =~ m{^0x[\da-f]+:0x[\da-f]+$}))
104
          {
105
        push @good, [$fw, $guid];
106
        print STDERR "Usable devices: /dev/$fw guid=$guid\n" if $verbose > 1;
107
          }
108
      }
109
      }
110
  }
111
112
my $all_commands = join("\n", get_ps());
113
while (@good && $all_commands =~ m{\b$good[0][1]\b})
114
  {
115
    print STDERR "already in use: /dev/$good[0][0] guid=$good[0][1]\n" if $verbose > 1;
116
    $fw{$good[0][0]}{in_use} = 1;
117
    shift @good;
118
  }
119
die "No usable devices: " . Dumper \%fw unless scalar @good;
120
$dvgrab_opts .= " -g '$good[0][1]'";
121
    
122
my $cmd = 'dvsource-command';
123
$cmd .= " --tally" if $tally;
124
$cmd .= " --verbose" if $verbose;
125
$cmd .= ' --retry' if $retry_connect;
126
$cmd .= " --port=$port" if defined $port;
127
$cmd .= " --host=$host" if defined $host;
128
129
print STDERR "+ $cmd '$dvgrab $dvgrab_opts -'\n" if $verbose;
130
system "$cmd '$dvgrab $dvgrab_opts -'" and die "failed to run '$cmd \"$dvgrab -noavc $dvgrab_opts -\"'\n";
131
exit 0;
132
133
#####################################################
134
sub get_ps()
135
{
136
  my @r = ();
137
  opendir DIR, "/proc/" or return @r;
138
  my @pids = grep { /^\d+$/ } readdir DIR;
139
  closedir DIR;
140
141
  for my $pid (@pids)
142
    {
143
      if (open IN, "<", "/proc/$pid/cmdline")
144
        {
145
          my $cmdline = <IN> || '';
146
          chomp $cmdline;
147
          push @r, $cmdline;
148
        }
149
    }
150
  return @r;
151
}
152