Audio-Nama

 view release on metacpan or  search on metacpan

lib/Audio/Nama/ChainSetup.pm  view on Meta::CPAN

use Audio::Nama::Globals qw($file $config $jack $setup %tn %bn %en $mode :trackrw $this_engine);
use Audio::Nama::Log qw(logsub logpkg);
use v5.36;
our $VERSION = 1.0;
use Data::Dumper::Concise;
use Storable qw(dclone);
use Audio::Nama::Util qw(signal_format input_node output_node);
use Audio::Nama::Assign qw(json_out);
no warnings 'uninitialized';

our (

	$g,  # routing graph object - 

		# based on project data 
		# the routing graph is generated,
		# then traversed over, and integrated
		# with track data to generate
		# Audio::Nama::IO objects. Audio::Nama::IO objects are iterated
		# over to generate 
		# the Ecasound chain setup text (c.f. chains command)

	@io, # IO objects corresponding to chain setup

	%is_ecasound_chain, # chains in final chain seutp

	# for sorting final result

	%inputs,
	%outputs,
	%post_input,
	%pre_output,

	# for final result
	
	@input_chains,	# list of input chain segments 
	@output_chains, # list of output chain segments
	@post_input,	# post-input chain operators
	@pre_output, 	# pre-output chain operators

	$chain_setup,	# final result as string
	);


sub remove_temporary_tracks {
	logsub((caller(0))[3]);
	map { logpkg(__FILE__,__LINE__,'debug',"removing temporary track ",$_->group.'/'.$_->name); $_->remove  } 
		grep{ $_->group eq 'Temp' } Audio::Nama::audio_tracks();
}
sub initialize {

	remove_temporary_tracks(); # we will generate them again
	$setup->{audio_length} = 0;  
	@io = (); 			# IO object list
	Audio::Nama::IO::initialize();
	$g = Graph->new(); 	
	%inputs = %outputs = %post_input = %pre_output = ();
	%is_ecasound_chain = ();
	@input_chains = @output_chains = @post_input = @pre_output = ();
	undef $chain_setup;
	Audio::Nama::disable_length_timer();
	reset_aux_chain_counter();
	unlink $file->chain_setup;
	$g;
}
sub ecasound_chain_setup { $chain_setup } 
sub is_ecasound_chain { $is_ecasound_chain{$_[0]} }

sub engine_tracks { Audio::Nama::audio_tracks() } 
sub engine_wav_out_tracks {
	grep{$_->rec} engine_tracks();
}
# return file output entries, including Mixdown 
sub really_recording { 
	my @files = map{ /-o:(.+?\.wav)$/} grep{ /-o:/ and /\.wav$/} split "\n", $chain_setup;
	wantarray() ? @files : scalar @files;
}
	
sub show_io {
	my $output = json_out( \%inputs ). json_out( \%outputs ); 
	Audio::Nama::pager( $output );
}

sub warn_missing_jack_clients {
	for my $track (Audio::Nama::audio_tracks()){
		$track->send_type =~ /jack_client/ and not $jack->{clients}->{$track->send_id}
		 	and Audio::Nama::throw("Track ".$track->name. qq(: JACK client ").$track->send_id.qq(" not found. Skipping aux send));
		$track->source_type eq 'jack_client' and not $jack->{clients}->{$track->source_id}
			and Audio::Nama::throw("Track ".$track->name. qq(: JACK client ").$track->source_id.qq(" not found. Skipping source connection));
	}
}

sub generate_setup_try {
	logsub((caller(0))[3]);

	my $extra_setup_code = shift;

	warn_missing_jack_clients();

	# start with bus routing
	
	map{ $_->apply($g) } Audio::Nama::Bus::all();

	logpkg(__FILE__,__LINE__,'debug',"Graph after bus routing:\n$g");
	
	# now various manual routing

	add_paths_for_aux_sends();
	logpkg(__FILE__,__LINE__,'debug',"Graph after aux sends:\n$g");

	add_paths_from_Main();
	logpkg(__FILE__,__LINE__,'debug',"Graph with paths from Main:\n$g");

	add_paths_for_mixdown_handling();
	logpkg(__FILE__,__LINE__,'debug',"Graph with mixdown mods:\n$g");
	
	$extra_setup_code->($g) if $extra_setup_code;

	prune_graph();
	logpkg(__FILE__,__LINE__,'debug',"Graph after pruning unterminated branches:\n$g");



( run in 1.139 second using v1.01-cache-2.11-cpan-39bf76dae61 )