File Coverage

blib/lib/Audio/Nama/Util.pm
Criterion Covered Total %
statement 21 125 16.8
branch 0 42 0.0
condition 0 22 0.0
subroutine 7 34 20.5
pod 0 27 0.0
total 28 250 11.2


line stmt bran cond sub pod time code
1             # ----------- Util.pm -----------
2              
3             # this package is for small subroutines with
4             # well-defined interfaces
5              
6             package Audio::Nama::Util;
7 1     1   5 use Modern::Perl;
  1         2  
  1         13  
8 1     1   109 use Carp;
  1         1  
  1         57  
9 1     1   6 use Data::Dumper::Concise;
  1         1  
  1         52  
10 1     1   5 use Audio::Nama::Assign qw(json_out);
  1         9  
  1         43  
11 1     1   5 use Audio::Nama::Globals qw(:all);
  1         2  
  1         457  
12 1     1   5 use Audio::Nama::Log qw(logit logsub logpkg);
  1         2  
  1         57  
13              
14 1     1   45 no warnings 'uninitialized';
  1         2  
  1         2559  
15              
16             require Exporter;
17              
18             our @ISA = qw(Exporter);
19              
20             our %EXPORT_TAGS = ( 'all' => [ qw(
21              
22             rw_set
23             freq
24             channels
25             input_node
26             output_node
27             signal_format
28             process_is_running
29             d1
30             d2
31             dn
32             round
33             colonize
34             time_tag
35             heuristic_time
36             dest_type
37             dest_string
38              
39             create_dir
40             join_path
41             wav_off
42             strip_all
43             strip_blank_lines
44             strip_comments
45             remove_spaces
46             expand_tilde
47             resolve_path
48             dumper
49              
50             ) ] );
51              
52             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
53              
54             our @EXPORT = ();
55              
56              
57             ## rw_set() for managing bus-level REC/MON/OFF settings commands
58             {
59             my %bus_logic = (
60             mix_track =>
61             {
62              
63             # setting mix track to REC
64            
65             REC => sub
66             {
67             my ($bus, $track) = @_;
68             $track->set_rec;
69             },
70              
71             # setting a mix track to PLAY
72            
73             PLAY => sub
74             {
75             my ($bus, $track) = @_;
76             $track->set_play;
77             },
78              
79             # setting a mix track to MON
80            
81             MON => sub
82             {
83             my ($bus, $track) = @_;
84             $track->set_mon;
85             },
86              
87             # setting mix track to OFF
88            
89             OFF => sub
90             {
91             my ($bus, $track) = @_;
92              
93             $track->set_off;
94              
95             # with the mix track off,
96             # the member tracks get pruned
97             # from the graph
98             }
99             },
100             member_track =>
101             {
102              
103             # setting member track to REC
104            
105             REC => sub
106             {
107             my ($bus, $track) = @_;
108              
109             $track->set_rec() or return;
110              
111             $bus->set(rw => MON);
112             $tn{$bus->send_id}->busify
113             if $bus->send_type eq 'track' and $tn{$bus->send_id};
114            
115             },
116              
117             # setting member track to MON
118            
119             MON => sub
120             {
121             my ($bus, $track) = @_;
122             $bus->set(rw => MON) if $bus->rw eq 'OFF';
123             $track->set_mon;
124             },
125              
126             # setting member track to PLAY
127            
128             PLAY => sub
129             {
130             my ($bus, $track) = @_;
131             $bus->set(rw => MON) if $bus->rw eq 'OFF';
132             $track->set_play;
133              
134             },
135             # setting member track to OFF
136              
137             OFF => sub
138             {
139             my ($bus, $track) = @_;
140             $track->set_off;
141             },
142             },
143             );
144             # for track commands 'rec', 'mon','off' we
145             # may toggle rw state of the bus as well
146             #
147              
148             sub rw_set {
149 0     0 0   logsub("&rw_set");
150 0           my ($bus,$track,$rw) = @_;
151 0 0         my $type = $track->is_mix_track
152             ? 'mix_track'
153             : 'member_track';
154 0           $bus_logic{$type}{uc $rw}->($bus,$track);
155             }
156             }
157              
158 0     0 0   sub freq { [split ',', $_[0] ]->[2] } # e.g. s16_le,2,44100
159              
160 0     0 0   sub channels { [split ',', $_[0] ]->[1] }
161            
162             # these are the names of loop devices corresponding
163             # to pre- and post-fader nodes of a track signal
164 0     0 0   sub input_node { $_[0].'_in' }
165 0     0 0   sub output_node {$_[0].'_out'}
166              
167             sub signal_format {
168 0     0 0   my ($template, $channel_count) = @_;
169 0           $template =~ s/N/$channel_count/;
170 0           my $format = $template;
171             }
172             sub process_is_running {
173 0     0 0   my $name = shift;
174 0           my @pids = split " ", qx(pgrep $name);
175 0           my @ps_ax = grep{ my $pid;
  0            
176             /$name/ and ! /defunct/
177             and ($pid) = /(\d+)/
178 0 0 0       and grep{ $pid == $_ } @pids
  0   0        
179             } split "\n", qx(ps ax) ;
180             }
181             sub d1 {
182 0     0 0   my $n = shift;
183 0           sprintf("%.1f", $n)
184             }
185             sub d2 {
186 0     0 0   my $n = shift;
187 0           sprintf("%.2f", $n)
188             }
189             sub dn {
190 0     0 0   my ($n, $places) = @_;
191 0           sprintf("%." . $places . "f", $n);
192             }
193             sub round {
194 0     0 0   my $n = shift;
195 0 0         return 0 if $n == 0;
196 0 0         $n = int $n if $n > 10;
197 0 0         $n = d2($n) if $n < 10;
198 0           $n;
199             }
200             sub colonize { # convert seconds to hours:minutes:seconds
201 0   0 0 0   my $sec = shift || 0;
202 0           my $hours = int ($sec / 3600);
203 0           $sec = $sec % 3600;
204 0           my $min = int ($sec / 60);
205 0           $sec = $sec % 60;
206 0 0         $sec = "0$sec" if $sec < 10;
207 0 0 0       $min = "0$min" if $min < 10 and $hours;
208 0 0         ($hours ? "$hours:" : "") . qq($min:$sec);
209             }
210              
211              
212              
213             sub time_tag {
214 0     0 0   my @time = localtime time;
215 0           $time[4]++;
216 0           $time[5]+=1900;
217 0           @time = @time[5,4,3,2,1,0];
218 0           sprintf "%4d.%02d.%02d-%02d:%02d:%02d", @time
219             }
220              
221             sub heuristic_time {
222 0     0 0   my $sec = shift;
223 0 0         d1($sec) . ( $sec > 120 ? " (" . colonize( $sec ) . ") " : " " )
224             }
225              
226             sub dest_type {
227 0     0 0   my $dest = shift;
228 0 0         if($dest eq undef ) { undef }
  0            
229              
230             # non JACK related
231              
232 0 0         if($dest eq 'bus') { 'bus' }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
233 0           elsif($dest eq 'null') { 'null' }
234 0           elsif($dest eq 'rtnull') { 'rtnull' }
235 0           elsif($dest =~ /^loop,/) { 'loop' }
236 0           elsif($dest !~ /\D/) { 'soundcard' } # digits only
237              
238             # JACK related
239              
240 0           elsif($dest =~ /^man/) { 'jack_manual' }
241 0           elsif($dest eq 'jack') { 'jack_manual' }
242 0           elsif($dest =~ /(^\w+\.)?ports/) { 'jack_ports_list' }
243 0           else { 'jack_client' }
244             }
245             sub dest_string {
246 0     0 0   my ($type, $id, $width) = @_;
247 0 0         if ($type eq 'soundcard'){
248 0           my $ch = $id;
249 0           my @channels;
250 0           push @channels, $_ for $ch .. ($ch + $width - 1);
251 0           join '/', @channels
252             }
253 0           else { $id }
254             }
255              
256             sub create_dir {
257 0     0 0   my @dirs = @_;
258 0           map{ my $dir = $_;
  0            
259 0           logpkg(__FILE__,__LINE__,'debug',"creating directory [ $dir ]");
260 0 0         -e $dir
261             #and (carp "create_dir: '$dir' already exists, skipping...\n")
262             or system qq( mkdir -p $dir)
263             } @dirs;
264             }
265              
266             sub join_path {
267            
268 0     0 0   my @parts = @_;
269 0           my $path = join '/', @parts;
270 0           $path =~ s(/{2,})(/)g;
271 0           $path;
272             }
273              
274             sub wav_off {
275 0     0 0   my $wav = shift;
276 0           $wav =~ s/\.wav\s*$//i;
277 0           $wav;
278             }
279              
280 0     0 0   sub strip_all{ strip_trailing_spaces(strip_blank_lines( strip_comments(@_))) }
281              
282             sub strip_trailing_spaces {
283 0     0 0   map {s/\s+$//} @_;
  0            
284 0           @_;
285             }
286             sub strip_blank_lines {
287 0     0 0   map{ s/\n(\s*\n)+/\n/sg } @_;
  0            
288 0           map{ s/^\n+//s } @_;
  0            
289 0           @_;
290            
291             }
292              
293             sub strip_comments { #
294 0     0 0   map{ s/#.*$//mg; } @_;
  0            
295 0           map{ s/\s+$//mg; } @_;
  0            
296              
297             @_
298 0           }
299              
300             sub remove_spaces {
301 0     0 0   my $entry = shift;
302             # remove leading and trailing spaces
303            
304 0           $entry =~ s/^\s*//;
305 0           $entry =~ s/\s*$//;
306            
307             # convert other spaces to underscores
308            
309 0           $entry =~ s/\s+/_/g;
310 0           $entry;
311             }
312             sub resolve_path {
313 0     0 0   my $path = shift;
314 0           $path = expand_tilde($path);
315 0           $path = File::Spec::Link->resolve_all($path);
316             }
317             sub expand_tilde {
318 0     0 0   my $path = shift;
319              
320 0           my $home = File::HomeDir->my_home;
321              
322              
323             # ~bob -> /home/bob
324 0           $path =~ s(
325             ^ # beginning of line
326             ~ # tilde
327             (\w+) # username
328             )
329 0           (File::HomeDir->users_home($1))ex;
330              
331             # ~/something -> /home/bob/something
332 0           $path =~ s(
333             ^ # beginning of line
334             ~ # tilde
335             / # slash
336             )
337             ($home/)x;
338 0           $path
339             }
340             sub dumper {
341 0 0 0 0 0   ! defined $_ and "undef"
      0        
      0        
      0        
342             or ! (ref $_) and $_
343             #or (ref $_) =~ /HASH|ARRAY/ and Audio::Nama::json_out($_)
344             or ref $_ and Dumper($_)
345             }
346              
347             1;
348             __END__