This file is indexed.

/usr/share/perl5/Audio/Nama/Bus.pm is in nama 1.208-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# ------------  Bus --------------------

package Audio::Nama::Bus;
use Modern::Perl; use Carp; 
use Audio::Nama::Log qw(logsub logpkg);
use Audio::Nama::Globals qw(:trackrw); 
our @ISA = qw( Audio::Nama::Object );

# share the following variables with subclasses

our $VERSION = 1.0;
our (%by_name);
use Audio::Nama::Object qw(
					name
					rw
					version 
					send_type
					send_id
					engine_group
					class

					);
sub initialize { 
	%by_name = (); 
};
sub new {
	my $class = shift;
	my %vals = @_;
	my @undeclared = grep{ ! $_is_field{$_} } keys %vals;
    croak "undeclared field: @undeclared" if @undeclared;
	if (! $vals{name}){
		Audio::Nama::throw("missing bus name");
		return
	}
	if ( $by_name{$vals{name}} ){ 
		Audio::Nama::throw("$vals{name}: bus name already exists. Skipping.")
			unless $Audio::Nama::quiet;
		return;
	}
	my $bus = bless { 
		class => $class, # for serialization, may be overridden
		rw   	=> MON, # for group control
		@_ }, $class;
	$by_name{$bus->name} = $bus;
}
sub group { $_[0]->name }


sub tracks { # returns list of track names in bus
	my $bus = shift;
	map{ $_->name } $bus->track_o;
}
sub track_o { 
	my $bus = shift;
	grep{ $_->group eq $bus->name } Audio::Nama::all_tracks();
}
sub last {
	#logpkg(__FILE__,__LINE__,'debug', "group: @_");
	my $bus = shift;
	my $max = 0;
	map{ 
		my $track = $_;
		my $last;
		$last = $track->last || 0;
		#print "track: ", $track->name, ", last: $last\n";

		$max = $last if $last > $max;

	} $bus->track_o;
	$max;
}

sub remove { Audio::Nama::throw($_[0]->name, " is system bus. No can remove.") }

{ my %allows = (REC => 'REC/MON', MON => MON, OFF => 'OFF');
sub allows { $allows{ $_[0]->rw } }
}
{ my %forces = (
		REC => 'REC (allows REC/MON)', 
		MON => 'MON (forces REC to MON)', 
		OFF => 'OFF (enforces OFF)'
 );
sub forces { $forces{ $_[0]->rw } }
}
	
## class methods

# sub buses, and Main
sub all { grep{ ! $Audio::Nama::config->{_is_system_bus}->{$_->name} } values %by_name };

sub overall_last { 
	my $max = 0;
	map{ my $last = $_->last; $max = $last if $last > $max  } all();
	$max;
}
sub settings_line {
	
	my ($mix,$bus) = @_;
	
	my $nothing = '-' x 77 . "\n";
	#return if $maybe_mix->name eq 'Master' or $maybe_mix->group eq 'Mastering';
	return unless defined $mix;

	my ($bustype) = $bus->class =~ /(\w+)$/;
	my $line = join " ", $bustype ,$bus->name,"is",$bus->forces;
	$line   .= " Version setting".$bus->version if $bus->version;
	#$line   .= "feeds", 
	$line .= " Mix track is ". $mix->rw;
	$line = "------[$line]";
	$line .= '-' x (77 - length $line);
	$line .= "\n";
	$line
}
	
sub trackslist {
	my $bus = shift;
	my $mix = $Audio::Nama::tn{$bus->send_id};
	my @list = ($mix,$bus);
	push @list, map{$Audio::Nama::tn{$_}} ($mix->name, $bus->tracks);
	\@list;
}

sub apply {}  # base class does no routing of its own


### subclasses
{
package Audio::Nama::SubBus;
use Modern::Perl; use Carp; our @ISA = 'Audio::Nama::Bus';
use Audio::Nama::Log qw(logsub logpkg);
use Audio::Nama::Util qw(input_node);
use Audio::Nama::Globals qw(:trackrw);

# connect source --> member_track --> mix_track

sub output_is_connectable {
 	my $bus = shift;

	# Either the bus's mix track is set to REC or MON
 	
 	$bus->send_type eq 'track' and $Audio::Nama::tn{$bus->send_id}->rec_status =~ /REC|MON/

	# Or, during mixdown, we connect bus member tracks to Master
	# even tho Master may be set to OFF
	
	or $bus->send_type eq 'track' 
				and $bus->send_id eq 'Master' 
				and $Audio::Nama::tn{Mixdown}->rec_status eq 'REC'
	
	# or we are connecting directly to a loop device
	or $bus->send_type eq 'loop' and $bus->send_id =~ /^\w+_(in|out)$/;
}

sub apply {
	no warnings 'uninitialized';
	my ($bus, $g)  = @_;
	logpkg(__FILE__,__LINE__,'debug', "bus ". $bus->name. ": applying routes");
	logpkg(__FILE__,__LINE__,'debug', "Bus destination is type: $bus->{send_type}, id: $bus->{send_id}");
	map{ 
		# connect member track input paths
		logpkg(__FILE__,__LINE__,'debug', "track ".$_->name);
		my @path = $_->input_path;
		$g->add_path(@path) if @path;
		logpkg(__FILE__,__LINE__,'debug',"input path: @path") if scalar @path;

		logpkg(__FILE__,__LINE__,'debug', join " ", "bus output:", $_->name, $bus->send_id);

		# connect member track outputs to target
		# disregard Master track rec_status when connecting
		# Main bus during mixdown handling

		Audio::Nama::Graph::add_path_for_send($g, $_->name, $bus->send_type, $bus->send_id )
			if $bus->output_is_connectable;
		
		# add paths for recording
		
		Audio::Nama::Graph::add_path_for_rec($g,$_) 
			if $_->rec_status eq REC
				and ! $Audio::Nama::mode->preview and ! $Audio::Nama::mode->doodle;

	} grep {$_->rec_status ne OFF} $bus->track_o;
}
sub remove {
	my $bus = shift;

	# all tracks returned to Main group
	map{$_->set(group => 'Main') } $bus->track_o;

	my $mix_track = $Audio::Nama::tn{$bus->name};

	if ( defined $mix_track ){
	 
		$mix_track->unbusify;
	
		# remove mix track unless it has some WAV files

		$mix_track->remove unless scalar @{ $mix_track->versions };
	}

	# remove bus from index
	
	delete $Audio::Nama::bn{$bus->name};
} 
}
{
package Audio::Nama::SendBusRaw;
use Modern::Perl; use Carp; our @ISA = 'Audio::Nama::Bus';
use Audio::Nama::Log qw(logsub logpkg);
sub apply {
	my $bus = shift;
	map{ 
		my @input_path = $_->input_path;
		$Audio::Nama::g->add_edge(@input_path);
		$Audio::Nama::g->set_edge_attributes( @input_path, 
			{ width => $Audio::Nama::tn{$_->target}->width });
		my @edge = ($_->name, Audio::Nama::output_node($bus->send_type));
		$Audio::Nama::g->add_edge(@edge);
		$Audio::Nama::g->set_edge_attributes( @edge, { 
			send_id => $bus->send_id,
			width => 2 }); # force to stereo 
	} grep{ $_->input_path } $bus->track_o;
}
sub remove {
	my $bus = shift;

	# delete all tracks
	map{$_->remove } $bus->track_o;

	# remove bus
	delete $by_name{$bus->name};
}
}
{
package Audio::Nama::SendBusCooked;
use Audio::Nama::Log qw(logsub logpkg);
use Modern::Perl; use Carp; our @ISA = 'Audio::Nama::SendBusRaw';

# graphic routing: target -> slave -> bus_send_type

sub apply {
	my $bus = shift;
	my $g = shift;
	map{ my @edge = ($_->name, Audio::Nama::output_node($bus->send_type));
		 $g->add_path( $_->target, @edge);
		 $g->set_edge_attributes( @edge, { 
				send_type => $bus->send_type,
				send_id => $bus->send_id,
				width => 2})
	} $bus->track_o;
}

}

# ---------- Bus routines --------
{
package Audio::Nama;
use Modern::Perl; use Carp;
use Audio::Nama::Util qw(dest_type);
our (
	$this_track,
	$this_bus,
	%tn,
	%bn,
);

sub set_current_bus {
	my $track = shift || ($this_track ||= $tn{Master});

	return unless $track; # needed for test environment

	# The current sequence changes when the user touches a
	# track that belongs to another sequence.
	
	$this_sequence = $bn{$track->group} if (ref $bn{$track->group}) =~ /Sequence/;

	my $bus_name = 
		$track->name =~ /Master|Mixdown/ 	
		? 'Main'
		: $track->is_mix_track()			
			? $track->name 
			: $track->group;
	
	select_bus($bus_name);
}
sub select_bus {
	my $name = shift;
	my $bus = $bn{$name} or return;
	$this_bus = $name;
	$this_bus_o = $bus;
}
sub add_bus {
	my ($name, @args) = @_; 
	
	Audio::Nama::SubBus->new( 
		name => $name, 
		send_type => 'track',
		send_id	 => $name,
		) unless $Audio::Nama::Bus::by_name{$name};

	@args = ( 
		rw 			=> MON,
		@args
	);

	$tn{$name} and Audio::Nama::pager_newline( qq($name: setting as mix track for bus "$name"));

	my $track = $tn{$name}// add_track($name, width => 2);

	$track->set( @args );
	
}
	
sub add_submix {

	my ($name, $dest_id, $bus_type) = @_;
	my $dest_type = dest_type( $dest_id );

	# dest_type: soundcard | jack_client | loop | jack_port | jack_multi
	
	logpkg(__FILE__,__LINE__,'debug',"name: $name, dest_type: $dest_type, dest_id: $dest_id");
	if ($bn{$name} and (ref $bn{$name}) !~ /SendBus/){
		Audio::Nama::throw($name,": bus name already in use. Aborting."), return;
	}
	if ($bn{$name}){
		Audio::Nama::pager_newline( qq(monitor bus "$name" already exists.  Updating with new tracks.) );
	} else {
	my @args = (
		name => $name, 
		send_type => $dest_type,
		send_id	 => $dest_id,
	);

	my $class = $bus_type eq 'cooked' ? 'Audio::Nama::SendBusCooked' : 'Audio::Nama::SendBusRaw';
	my $bus = $class->new( @args );

	$bus or carp("can't create bus!\n"), return;

	}
	map{ Audio::Nama::EarTrack->new(	name => "$name\_$_", # BusName_TrackName
							rw => MON,
							target => $_,
							group  => $name,
							width => 2,
							hide	=> 1,
						)
   } $bn{Main}->tracks;
		
}

	
sub update_submix {
	my $name = shift;
		add_submix( $name, 
						 $bn{$name}->send_id),
						 "dummy",
}
sub remove_submix_helper_tracks {
	my $name = shift;
	#say "got name: $name";
	my @submixes = submixes(); 
	#say "got submixes:", Dumper \@submixes;
	for my $sm ( @submixes ){ 
		my $to_remove = join '_', $sm->name, $name;
		#say "to_remove: $to_remove";
		local $quiet;
		$quiet++;
		for my $name ($sm->tracks) { 
			$tn{$name}->remove, last if $name eq $to_remove
		}
	}

}
sub submixes { grep { (ref $_) =~ /SendBusCooked/ } values %Audio::Nama::Bus::by_name }

}
1;
__END__