#!/usr/bin/env perl

# Play and clock a MIDI device, like a drum machine or sequencer.
# Examples:
#   perl eg/grooves.pl wavetable 90 # on windows
#   perl eg/grooves.pl fluid 90 # with fluidsynth
#   perl eg/grooves.pl fluid 100 9 house # specify style category
#   perl eg/grooves.pl fluid 100 9 * hop # no categeory; only named
#   perl eg/grooves.pl usb 100 -1 # multi-timbral device

use v5.36;
use Data::Dumper::Compact 'ddc';
use MIDI::Drummer::Tiny::Grooves ();
use Music::SimpleDrumMachine ();

my $port = shift || 'usb';
my $bpm  = shift || 120;
my $chan = shift // 9;
my $cat  = shift // 'rock';
my $name = shift // '';

my $grooves = MIDI::Drummer::Tiny::Grooves->new(
    return_patterns => 1,
    # share_file => '/Users/gene/sandbox/MIDI-Drummer-Tiny/share/drum-pattern-bit-strings.txt',
);

$cat  = undef if $cat eq '*';
$name = undef if $name eq '*';
my $set;
$set = $grooves->search({ cat => $cat }) if $cat;
$set = $grooves->search({ name => $name }, $set) if $name;
die "No matching grooves for $cat + $name\n" unless keys %$set;
say scalar(keys %$set), " grooves found.\n";

my $dm = Music::SimpleDrumMachine->new(
    port_name => $port,
    bpm       => $bpm,
    chan      => $chan,
    next_part => 'part',
    parts     => { part => \&part },
    verbose   => 1,
);

sub part {
    say 'part';
    my $groove = $grooves->get_groove(0, $set); # get a random groove
    # not crazy about only crashing, like with some funk grooves
    $groove->{groove}{closed} = delete $groove->{groove}{cymbal}
        if !exists($groove->{groove}{closed}) && exists($groove->{groove}{cymbal});
    my %patterns = $grooves->groove($groove->{groove});
    say $groove->{name}, ' ', ddc \%patterns;
    my $next = 'part';
    return $next, \%patterns;
}