Audio-Nama
view release on metacpan or search on metacpan
lib/Audio/Nama/Persistence.pm view on Meta::CPAN
# ---------- Persistent State Support -------------
package Audio::Nama;
use File::Copy;
use v5.36; no warnings 'uninitialized';
use vars '$VERSION';
sub save_state {
logsub((caller(0))[3]);
my $filename = shift;
my $path = $filename || $file->state_store();
# remove extension if present
$filename =~ s/\.json//;
# append filename if warranted
$filename =
$filename =~ m{/}
? $filename # as-is if input contains slashes
: join_path(project_dir(),$filename) ;
$project->{nama_version} = $VERSION;
# store playback position, if possible
$project->{playback_position} = ecasound_iam("getpos") if $this_engine->valid_setup();
# some stuff get saved independently of our state file
logpkg(__FILE__,__LINE__,'debug', "saving palette");
$ui->save_palette;
logpkg(__FILE__,__LINE__,'debug',"Saving state as ", $path);
save_system_state($path);
save_global_effect_chains();
save_midish();
# store alsa settings
if ( $config->{opts}->{a} ) {
my $filename = $filename;
$filename =~ s/\.yml$//;
pager("storing ALSA settings\n");
pager(qx(alsactl -f $filename.alsa store))
}
}
sub initialize_marshalling_arrays {
@tracks_data = (); # zero based, iterate over these to restore
@bus_data = (); #
@marks_data = ();
@fade_data = ();
@inserts_data = ();
@effects_data = ();
@edit_data = ();
@project_effect_chain_data = ();
@global_effect_chain_data = ();
}
sub save_system_state {
my $path = shift;
my $output_format = shift;
sync_effect_parameters(); # in case a controller has made a change
# we sync read-only parameters, too, but I think that is
# harmless
lib/Audio/Nama/Persistence.pm view on Meta::CPAN
my $max = scalar @{$text->{command_history}};
$max = 50 if $max > 50;
my $hist = $text->{command_history};
@$hist = @$hist[-$max..-1];
$text->{command_index} = $max;
logpkg(__FILE__,__LINE__,'debug', "serializing");
my @formats = $output_format || $config->serialize_formats;
map{ my $format = $_ ;
serialize(
file => $path,
format => $format,
vars => [ (grep {! /save_file_version_number/ } @tracked_vars) ],
class => 'Audio::Nama',
);
} @formats;
serialize(
file => $file->untracked_state_store,
format => 'json',
vars => [ (grep {! /save_file_version_number/ } @persistent_vars) ],
class => 'Audio::Nama',
);
"$path.json";
}
{ my %decode =
(
json => \&json_in,
yaml => sub
{
my $yaml = shift;
# remove empty key hash lines to satisfy YAML::Tiny
$yaml = join $/, grep{ ! /^\s*:/ } split $/, $yaml;
$yaml = quote_yaml_scalars( $yaml );
yaml_in($yaml);
},
perl => sub {my $perl_source = shift; eval $perl_source},
storable => sub { my $bin = shift; thaw( $bin) },
);
# allow dispatch by either file format or suffix
@decode{qw(yml pl bin)} = @decode{qw(yaml perl storable)};
sub decode {
my ($source, $suffix) = @_;
$decode{$suffix}
or die qq(key $suffix: expecting one of).join q(,),keys %decode;
$decode{$suffix}->($source);
}
}
sub restore_state_from_file {
logsub((caller(0))[3]);
my $filename = shift;
$filename //= $file->state_store();
initialize_marshalling_arrays();
my $suffix = 'json';
my $path = $file->untracked_state_store;
if (-r $path)
{
my $source = read_file($path);
my $ref = decode($source, $suffix);
assign(
data => $ref,
vars => \@persistent_vars,
class => 'Audio::Nama');
assign_singletons( { data => $ref });
}
$path = $filename;
if (-r $path)
{
my $source = read_file($path);
my $ref = decode($source, $suffix);
assign(
data => $ref,
vars => \@tracked_vars,
class => 'Audio::Nama');
# perform assignments for singleton
# hash entries (such as $fx->{ applied});
# that that assign() misses
assign_singletons({ data => $ref });
}
restore_global_effect_chains();
####### Backward Compatibility ########
$project->{nama_version} //= delete $project->{save_file_version_number};
if ( $project->{nama_version} < 1.100){
map{ Audio::Nama::EffectChain::move_attributes($_) }
(@project_effect_chain_data, @global_effect_chain_data)
}
if ( $project->{nama_version} < 1.105){
map{ $_->{class} = 'Audio::Nama::BoostTrack' }
grep{ $_->{name} eq 'Boost' } @tracks_data;
}
if ( $project->{nama_version} < 1.109){
map
{ if ($_->{class} eq 'Audio::Nama::MixTrack') {
$_->{is_mix_track}++;
$_->{class} = $_->{was_class};
$_->{class} = 'Audio::Nama::Track';
}
lib/Audio/Nama/Persistence.pm view on Meta::CPAN
map{
my %h = %$_;
my $fade = Audio::Nama::Fade->new( %h ) ;
} @fade_data;
# edits
map{
my %h = %$_;
my $edit = Audio::Nama::Edit->new( %h ) ;
} @edit_data;
# restore command history
#$text->{term}->SetHistory(@{$text->{command_history}})
# if (ref $text->{command_history}) =~ /ARRAY/;
;
# restore effect chains and profiles
%Audio::Nama::EffectChain::by_index = ();
#say "Project Effect Chain Data\n", json_out( \@project_effect_chain_data);
map { my $fx_chain = Audio::Nama::EffectChain->new(%$_) }
(@project_effect_chain_data, @global_effect_chain_data);
my $fname = $file->midi_store;
midish_cmd(qq<load "$fname">);
}
sub convert_rw {
my $h = shift;
$h->{rw} = MON, return if $h->{rw} eq 'REC' and ($h->{rec_defeat} or $h->{is_mix_track});
$h->{rw} = PLAY, return if $h->{rw} eq 'MON';
}
sub is_nonempty_hash {
my $ref = shift;
return if (ref $ref) !~ /HASH/;
return (keys %$ref);
}
sub save_global_effect_chains {
@global_effect_chain_data = map{ $_->as_hash } Audio::Nama::EffectChain::find(global => 1);
# always save global effect chain data because it contains
# incrementing counter
map{ my $format = $_ ;
serialize(
file => $file->global_effect_chains,
format => $format,
vars => \@global_effect_chain_vars,
class => 'Audio::Nama',
);
} $config->serialize_formats;
}
sub restore_global_effect_chains {
logsub((caller(0))[3]);
my $path = $file->global_effect_chains;
-r $path or return;
my $source = read_file($path);
throw("$path: empty file"), return unless $source;
my $suffix = 'json';
my $ref = decode($source, $suffix);
assign(
data => $ref,
vars => \@global_effect_chain_vars,
class => 'Audio::Nama');
assign_singletons({ data => $ref });
}
1;
__END__
( run in 1.451 second using v1.01-cache-2.11-cpan-0b58ddf2af1 )