File Coverage

blib/lib/Audio/JackMiniMix.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package Audio::JackMiniMix;
2              
3             ################
4             #
5             # JackMiniMix: perl control interface
6             #
7             # Copyright 2005 Nicholas J. Humfrey
8             #
9              
10 1     1   11643 use Carp;
  1         2  
  1         5439  
11              
12 1     1   1784 use Net::LibLO;
  0            
  0            
13             use strict;
14              
15             use vars qw/$VERSION $ATTEMPTS/;
16              
17             $VERSION="0.02";
18             $ATTEMPTS=5;
19              
20              
21             sub new {
22             my $class = shift;
23            
24             croak( "Missing JackMiniMix server port or URL" ) if (scalar(@_)<1);
25              
26             # Bless the hash into an object
27             my $self = {
28             channel_count => 0,
29             channels => {},
30             pong => 0
31             };
32             bless $self, $class;
33              
34             # Create address of JackMiniMix server
35             $self->{addr} = new Net::LibLO::Address( @_ );
36             if (!defined $self->{addr}) {
37             carp("Error creating Net::LibLO::Address");
38             return undef;
39             }
40            
41             # Create new LibLO instance
42             $self->{lo} = new Net::LibLO();
43             if (!defined $self->{lo}) {
44             carp("Error creating Net::LibLO");
45             return undef;
46             }
47            
48             # Add reply handlers
49             $self->{lo}->add_method( '/mixer/channel/gain', 'if', \&_channel_gain_handler, $self );
50             $self->{lo}->add_method( '/mixer/channel/label', 'is', \&_channel_label_handler, $self );
51             $self->{lo}->add_method( '/mixer/channel_count', 'i', \&_channel_count_handler, $self );
52             $self->{lo}->add_method( '/pong', '', \&_pong_handler, $self );
53            
54             # Get the number of channels
55             if (!$self->channel_count()) {
56             carp("JackMiniMix server is not responding");
57             return undef;
58             }
59              
60             return $self;
61             }
62              
63             sub channel_count {
64             my $self=shift;
65             $self->{channel_count} = 0;
66             $self->_wait_reply( '/mixer/get_channel_count' );
67             return $self->{channel_count};
68             }
69              
70             sub _channel_count_handler {
71             my ($serv, $mesg, $path, $typespec, $userdata, @params) = @_;
72             $userdata->{channel_count}=$params[0];
73             return 0; # Success
74             }
75              
76             sub get_channel_gain {
77             my $self=shift;
78             my ($channel) = @_;
79             croak "Total number of channels is unknown" unless ($self->{channel_count});
80             $self->{channels}->{$channel}->{gain} = undef;
81             $self->_wait_reply( '/mixer/channel/get_gain', 'i', $channel );
82             return $self->{channels}->{$channel}->{gain};
83             }
84              
85             sub set_channel_gain {
86             my $self=shift;
87             my ($channel,$gain) = @_;
88             croak "Total number of channels is unknown" unless ($self->{channel_count});
89             $self->_wait_reply( '/mixer/channel/set_gain', 'if', $channel, $gain );
90             return 1 if ($self->{channels}->{$channel}->{gain} == $gain);
91             return 0; # Failed
92             }
93              
94             sub _channel_gain_handler {
95             my ($serv, $mesg, $path, $typespec, $userdata, @params) = @_;
96             my ($channel, $gain) = @params;
97            
98             # Check channel exists
99             if (!exists $userdata->{channels}->{$channel}) {
100             $userdata->{channels}->{$channel} = {};
101             }
102            
103             # Store the gain
104             $userdata->{channels}->{$channel}->{gain} = $gain;
105            
106             return 0; # Success
107             }
108              
109              
110             sub get_channel_label {
111             my $self=shift;
112             my ($channel) = @_;
113             croak "Total number of channels is unknown" unless ($self->{channel_count});
114             $self->{channels}->{$channel}->{label} = undef;
115             $self->_wait_reply( '/mixer/channel/get_label', 'i', $channel );
116             return $self->{channels}->{$channel}->{label};
117             }
118              
119             sub set_channel_label {
120             my $self=shift;
121             my ($channel,$label) = @_;
122             croak "Total number of channels is unknown" unless ($self->{channel_count});
123             $self->_wait_reply( '/mixer/channel/set_label', 'is', $channel, $label );
124             return 1 if ($self->{channels}->{$channel}->{label} == $label);
125             return 0; # Failed
126             }
127              
128             sub _channel_label_handler {
129             my ($serv, $mesg, $path, $typespec, $userdata, @params) = @_;
130             my ($channel, $label) = @params;
131            
132             # Check channel exists
133             if (!exists $userdata->{channels}->{$channel}) {
134             $userdata->{channels}->{$channel} = {};
135             }
136            
137             # Store the label
138             $userdata->{channels}->{$channel}->{label} = $label;
139            
140             return 0; # Success
141             }
142              
143             sub ping {
144             my $self=shift;
145             $self->{pong} = 0;
146             $self->_wait_reply( '/ping' );
147             return $self->{pong};
148             }
149              
150             sub _pong_handler {
151             my ($serv, $mesg, $path, $typespec, $userdata, @params) = @_;
152             $userdata->{pong}++;
153             return 0; # Success
154             }
155              
156             sub get_url {
157             my $self=shift;
158             return $self->{addr}->get_url();
159             }
160              
161              
162             sub _wait_reply {
163             my $self=shift;
164             my (@args) = @_;
165             my $bytes = 0;
166            
167             # Throw away any old incoming messages
168             for(1..$ATTEMPTS) { $self->{lo}->recv_noblock( 0 ); }
169              
170             # Try a few times
171             for(1..$ATTEMPTS) {
172            
173             # Send Query
174             my $result = $self->{lo}->send( $self->{addr}, @args );
175             if ($result<1) {
176             warn "Failed to send message (".join(',',@args)."): ".$self->{addr}->errstr()."\n";
177             sleep(1);
178             next;
179             }
180              
181             # Wait for reply within one second
182             $bytes = $self->{lo}->recv_noblock( 1000 );
183             if ($bytes<1) {
184             warn "Timed out waiting for reply after one second.\n";
185             } else { last; }
186             }
187            
188             # Failed to get reply ?
189             if ($bytes<1) {
190             warn "Failed to get reply from JackMiniMix server after $ATTEMPTS attempts.\n";
191             }
192            
193             return $bytes;
194             }
195              
196              
197             1;
198              
199             __END__