ONO::FW::Edu::Apps::Modules::DrumComputer

package ONO::FW::Edu::Apps::Modules::DrumComputer;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2022-2026 Jos Kirps and The Joopita Project [ASBL]
# Copyright (C) 2011-2022 Jos Kirps and Joopita Research ASBL
# Copyright (C) 2006-2011 Jos Kirps and The Joopita Project
# Copyright (C) 2001-2006 Jos Kirps and The WobbleWolf Project
#
# This file, as well as many other parts of the ONO Software Project or
# related elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################

#: This module is a front end application module wrapper that has been
#: created for the Morzino Project (morzino.com) and that has been released
#: as Open Source software.
#:
#: Note that this is NOT a self-contained application, it is only a wrapper
#: that makes heavy use of the ONO Perl Framework application engine.

use strict;

use Encode;

use ONO::Render;

use ONO::ToolBox::Auth;
use ONO::Lib::Lang::LangKitEdu;

use ONO::Lib::DateTime::ToolBox;

use ONO::FW::Apps::Core;
use ONO::FW::Apps::Core::Graphics;

use ONO::FW::Edu::Apps::ToolBox;
use ONO::FW::User::Init;

use ONO::IO;
use ONO::DB;
use ONO::Lib::Basic;

sub play {

my (
$self,
$option,
$vars_ref,
$HTTP,
$BASE,
) = @_;

################################################################
# INIT - BEGIN
################################################################

my (
$db,
$community,
$action_url,
$form,
$format,
$canvas,
$pdfkey,
$sec,$min,$hour,
$mday,$mon,$year,
$wday,$yday,$timestamp,
$lang,
$BLK_ref,
$vars_ref,
) = ONO::FW::Apps::Core->init($vars_ref);

my %vars = %$vars_ref;
my %BLK = %$BLK_ref;

my ($HEAD,$WEB);

my (
$vpath,
$lang,$domain,$community,
$sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$timestamp,
$script_url,$action_url,$form
) = ONO::FW::User::Init->getvar(\%vars);

ONO::FW::Apps::Core->now("","chess",$vars{'app_lang'});

my $action_url = qq~$ENV{'SCRIPT_NAME'}?app_lang=$vars{'app_lang'}&~;

###################################################################
# DAUDIO
###################################################################

my $CSSJS = ONO::Render->cssjs($BASE);

my $SEQ = "tone-step-sequencer-alt8";
my $NUMS = "0, 1, 2, 3, 4, 5, 6, 7";
my $BUT8 = "_yellow";
my $BUT16;
my $SEQ_CLASS = " auto w80";

if ($vars{'cols'} == 16) {

$SEQ = "tone-step-sequencer";
$NUMS = "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15";
$BUT8 = "";
$BUT16 = "_yellow";
$SEQ_CLASS = "";

} else {

$vars{'cols'} = 8;

}

my $AUDIO = qq~<div style="background-color:#555555;overflow:hidden">
<div class="p20 mb30">
<tone-loader></tone-loader>
<tone-transport></tone-transport>
</div>
<div class="abs p20" style="top:0px;left:120px">
<a href="$action_url&cols=8" class="button$BUT8 button_big button_left">8</a>
<a href="$action_url&cols=16" class="button$BUT16 button_big button_right">16</a>
</div>
<div class="p10 bg_title mb10$SEQ_CLASS">
<$SEQ></$SEQ>
</div>
</div>
<script>
var keys = new Tone.Players({
"kick" : "$BASE/ono/osr/audio/sequencer/default/kick.wav",
"snare" : "$BASE/ono/osr/audio/sequencer/default/snare.wav",
"hat" : "$BASE/ono/osr/audio/sequencer/default/hat.wav",
"clap" : "$BASE/ono/osr/audio/sequencer/default/clap.wav",
}, {
"volume" : -10,
"fadeOut" : "64n",
}).toMaster();
//the notes
var noteNames = ["kick", "snare", "hat", "clap"];
var loop = new Tone.Sequence(function(time, col){
var column = document.querySelector("$SEQ").currentColumn;
column.forEach(function(val, i){
if (val){
//slightly randomized velocities
var vel = Math.random() * 0.5 + 0.5;
keys.get(noteNames[i]).start(time, 0, "32n", 0, vel);
}
});
Tone.Draw.schedule(function(){
document.querySelector("$SEQ").setAttribute("highlight", col);
}, time);
}, [$NUMS], "$vars{'cols'}n").start(0);
document.querySelector("tone-transport").bind(Tone.Transport);
Tone.Transport.on("stop", () => {
setTimeout(() => {
document.querySelector("$SEQ").setAttribute("highlight", "-1");
}, 100);
});
</script>
~;

my $RAND;
if (ONO::IO->devstation) {
$RAND = "?".int(rand(999999));
}

print qq~Content-Type: text/html; charset=UTF-8\n\n
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="Generator" content="ONO App Engine">
$CSSJS
<script src="$BASE/ono/osr/javascript/tone/js/alt_1/Tone.min.js$RAND"></script>
<script src="$BASE/ono/osr/javascript/tone/js/alt_1/tonejs-ui.js$RAND"></script>
</head>
<body style="margin:0px;padding:0px">
$AUDIO
</body>
</html>
~;
}

###################################################################
#### THAT'S IT :-D
###################################################################

1;

__END__