{
my
(
$pid
,
$sel
);
my
@handles
=
my
(
$fh_midi_write
,
$fh_midi_read
,
$fh_midi_error
) =
map
{ IO::Handle->new() } 1..3;
map
{
$_
->autoflush(1) }
@handles
;
sub
start_midish_process {
logsub((
caller
(0))[3]);
my
$executable
=
qx(which midish)
;
chomp
$executable
;
$executable
or
say
(
"Midish not found!"
),
return
;
$pid
= open3(
$fh_midi_write
,
$fh_midi_read
,
$fh_midi_error
,
"$executable -v"
)
or
warn
"Midish failed to start!"
;
$sel
= IO::Select->new();
$sel
->add(
$fh_midi_read
);
$sel
->add(
$fh_midi_error
);
midish_cmd(
qq(print "Midish is ready.")
);
write_aux_midi_commands();
midish_cmd(
q(exec ")
.
$file
->aux_midi_commands.
q(")
);
$pid
}
sub
midish_cmd {
my
$command
=
shift
;
logsub((
caller
(0))[3]);
return
unless
$config
->{use_midi};
print
$fh_midi_write
"$command\n"
;
$project
->{midi_history} //=[];
push
@{
$project
->{midi_history} },
$command
;
my
$length
= 2**16;
sleeper(0.05);
my
@result
;
foreach
my
$h
(
$sel
->can_read)
{
my
$buf
=
''
;
if
(
$h
eq
$fh_midi_error
)
{
sysread
(
$fh_midi_error
,
$buf
,
$length
);
if
(
$buf
){
print
"MIDISH ERR-> $buf\n"
}
}
else
{
sysread
(
$fh_midi_read
,
$buf
,
$length
);
if
(
$buf
){
push
@result
,
grep
{ !/\+ready/ }
split
"\n"
,
$buf
}
}
}
join
"\n"
,
@result
;
}
sub
close_midish {
save_midish();
say
"reaping midish"
;
kill_and_reap(
$pid
);
}
sub
save_midish {
my
$fname
=
$file
->midi_store;
midish_cmd(
qq<save "$fname">
);
}
sub
reconfigure_midi {
add_midi_track(
$config
->{midi_record_buffer},
n
=> 999,
hide
=> 1)
if
not
$tn
{
$config
->{midi_record_buffer}}
and
$this_track
->current_midi
and
$this_track
->rec;
my
$midi_rec
=
$tn
{
$config
->{midi_record_buffer}};
my
@all
=
$bn
{Midi}->track_o;
$_
->mute
for
@all
;
my
@audible
=
grep
{
$_
->play }
@all
;
$_
->unmute
for
@audible
;
do
{
$_
->select_track; midish_cmd(
"fdel "
.
$_
->name) }
for
@all
;
do
{
$_
->select_track; midish_cmd(
join
' '
,
'rnew'
,
$_
->source_id,
$_
->send_id) }
for
@audible
;
my
(
$rec
) =
my
@rec
=
$en
{midish}->rec_tracks;
return
unless
@rec
;
throw(
"more than one midi REC track "
,
join
" "
,
map
{
$_
->name}
@rec
),
return
if
@rec
> 1;
$rec
->mute;
$midi_rec
->select_track;
my
$cmd
=
'rnew'
;
$cmd
=
join
' '
,
$cmd
,
$rec
->source_id,
$rec
->send_id;
midish_cmd(
$cmd
);
}
sub
start_midi_transport {
my
$start_command
=
$en
{midish}->rec_tracks ?
'r'
:
'p'
;
midish_cmd(
$start_command
);
$setup
->{midish_running}++;
}
sub
stop_midi_transport {
return
unless
midish_running();
midish_cmd(
's'
);
delete
$setup
->{midish_running};
}
sub
midi_rec_cleanup {
my
(
$track
) =
$en
{midish}->rec_tracks;
defined
$track
or
return
;
my
$length
= midish_cmd(
'print [mend]'
);
$length
> 0 or
return
;
my
$version
=
$track
->current_version;
$track
->set_version(
$version
);
push
@{
$track
->midi_versions},
$version
;
$track
->set(
rw
=> PLAY);
my
$cmd
=
join
' '
,
'chdup'
,
$config
->{midi_record_buffer},
$track
->source_id,
$track
->midi_version;
say
"cmd: $cmd"
;
midish_cmd(
$cmd
);
midish_cmd(
"clr $config->{midi_record_buffer} $length"
);
$track
->unmute();
save_midish();
}
}
sub
write_aux_midi_commands {
write_file(
$file
->aux_midi_commands, get_data_section(
'aux_midi_commands'
))
unless
-e
$file
->aux_midi_commands
}
sub
add_midi_track {
my
(
$name
,
@args
) =
@_
;
my
$track
= Audio::Nama::add_track(
$name
,
class
=>
'Audio::Nama::MidiTrack'
,
group
=>
'Midi'
,
source_id
=>
'midi'
,
source_type
=>
'midi'
,
midi_versions
=> [],
novol
=> 1,
engine_group
=>
$config
->{midi_engine_name},
nopan
=> 1,
@args
,
);
}
sub
user_midi_tracks {
grep
{
$_
->class =~ /Midi/ }
grep
{ !
$_
->hide } all_tracks() }
1;