The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Audio::Nama::Sequence;
use Modern::Perl; use Carp; 
use Audio::Nama::Assign qw(json_out);
use Audio::Nama::Log qw(logsub logpkg);
use Audio::Nama::Effects qw(fxn modify_effect);
use Audio::Nama::Object qw( items clip_counter );
use Audio::Nama::Globals qw(:trackrw);
our @ISA = 'Audio::Nama::SubBus';
our $VERSION = 1.0;
use SUPER;
our %by_name; # alias to %Audio::Nama::Bus::by_name
*by_name = \%Audio::Nama::Bus::by_name; 

sub new { 
	my ($class,%args) = @_;
	# take out args we will process
	my $items = delete $args{items};
	my $counter = delete $args{clip_counter};
	#logpkg(__FILE__,__LINE__,'debug', "items: ",map{json_out($_->as_hash)}map{$Audio::Nama::tn{$_}}@$items) if $items;
	$items //= [];
	@_ = ($class, %args);
	my $self = super();
	logpkg(__FILE__,__LINE__,'debug',"new object: ", json_out($self->as_hash));
	logpkg(__FILE__,__LINE__,'debug', "items: ",json_out($items));
	$self->{clip_counter} = $counter;
	$self->{items} = $items;
	$Audio::Nama::this_sequence = $self;
	$self;
} 
sub clip {
	my ($self, $index) = @_;
	return 0 if $index <= 0;
	$Audio::Nama::tn{$self->{items}->[$index - 1]}
}
sub rw { 
	my $self = shift;
	$Audio::Nama::mode->{offset_run} ? OFF : $self->{rw}
}
# perl indexes arrays at zero, for nama users we number items from one
sub insert_item {
	my $self = shift;
	my ($item, $index) = @_;
	$self->append_item($item), return if $index == @{$self->{items}} + 1;
	$self->verify_item($index) or die "$index: sequence index out of range";
	splice @{$self->{items}}, $index - 1,0, $item->name 
}
sub verify_item {
	my ($self, $index) = @_;
	$index >= 1 and $index <= scalar @{$self->items} 
}
sub delete_item {
	my $self = shift;
	my $index = shift;
	$self->verify_item($index) or die "$index: sequence index out of range";
	my $trackname = splice(@{$self->{items}}, $index - 1, 1);
	$Audio::Nama::tn{$trackname} and $Audio::Nama::tn{$trackname}->remove;
}
sub append_item {
	my $self = shift;
	my $item = shift;
	push( @{$self->{items}}, $item->name );
}
sub item {
	my $self = shift;
	my $index = shift;
	return 0 if $index <= 0;
	$Audio::Nama::tn{$self->{items}->[$index - 1]};
}
sub list_output {
	my $self = shift;
	my $i;
	join "\n","Sequence $self->{name} clips:",
		map { join " ", 
				++$i, 
				$Audio::Nama::tn{$_}->n,
				$_,
				sprintf("%.3f %.3f", $Audio::Nama::tn{$_}->duration, $Audio::Nama::tn{$_}->endpoint),
		} @{$self->items}
}
sub remove {
	my $sequence = shift;

	# delete all clips
	map{$Audio::Nama::tn{$_}->remove } $by_name{$sequence->name}->tracks;

	# delete clip array
	delete $sequence->{items};
	
	my $mix_track = $Audio::Nama::tn{$sequence->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 sequence from index
	
	delete $by_name{$sequence->name};
} 
sub new_clip {
	my ($self, $track, %args) = @_; # $track can be object or name
	my $markpair = delete $args{region};
	logpkg(__FILE__,__LINE__,'debug',json_out($self->as_hash), json_out($track->as_hash));
	ref $track or $track = $Audio::Nama::tn{$track} 
		or die("$track: track not found."); 
	my %region_args = (
		region_start => $markpair && $markpair->[0]->name || $track->region_start,
		region_end	 => $markpair && $markpair->[1]->name || $track->region_end
	);
	my $clip = Audio::Nama::Clip->new(
		target => $track->basename,
		name => $self->unique_clip_name($track->name, $track->monitor_version),
		rw => PLAY,
		group => $self->name,
		version => $track->monitor_version,
		hide => 1,
		%region_args,
		%args
	);
	modify_effect( $clip->vol, 1, undef, fxn($track->vol)->params->[0]);
	modify_effect( $clip->pan, 1, undef, fxn($track->pan)->params->[0]);
	$clip
}
sub new_spacer {
	my( $self, %args ) = @_;
	my $position = delete $args{position};
	my $spacer = Audio::Nama::Spacer->new( 
		duration => $args{duration},
		name => $self->unique_spacer_name(),
		rw => OFF,
		group => $self->name,
	);
	$self->insert_item( $spacer, $position || ( scalar @{ $self->{items} } + 1 ))
}
sub unique_clip_name {
	my ($self, $trackname, $version) = @_;
	join '-', $self->name , ++$self->{clip_counter}, $trackname, 'v'.$version;
}
sub unique_spacer_name {
	my $self = shift;
	join '-', $self->name, ++$self->{clip_counter}, 'spacer';
}
package Audio::Nama;

sub new_sequence {

	my %args = @_;
	my $name = $args{name};
	my @tracks = defined $args{tracks} ? @{ $args{tracks} } : ();
	my $group = $args{group} || 'Main';
	my $mix_track = $tn{$name} || add_track($name, group => $group);
	$mix_track->set( rw 			=> MON);
	my $sequence = Audio::Nama::Sequence->new(
		name => $name,
		send_type => 'track',
		send_id	 => $name,
	);
;
	map{ $sequence->append_item($_) }
	map{ $sequence->new_clip($_)} @tracks;
	$this_sequence = $sequence;

}
sub compose_sequence {
	my ($sequence_name, $track, $markpairs) = @_;
	logpkg(__FILE__,__LINE__,'debug',"sequence_name: $sequence_name, track:", $track->name, 
			", markpairs: ",Audio::Nama::Dumper $markpairs);

	my $sequence = new_sequence( name => $sequence_name);
	logpkg(__FILE__,__LINE__,'debug',"sequence\n",Audio::Nama::Dumper $sequence);
	my @clips = map { 
		$sequence->new_clip($track, region => $_) 
	} @$markpairs;
	map{ $sequence->append_item($_) } @clips;
	$sequence
}
1
__END__