<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/halo"
               xmlns:d="http://ns.adobe.com/fxg/2008/dt"
               xmlns:ai="http://ns.adobe.com/ai/2009" 
               xmlns:igimc="com.igetitmusic.components.*"
               xmlns:i="com.igetitmusic.components.intervalSlider.*"
               xmlns:k="com.igetitmusic.components.keyboard.*"
               xmlns:j="com.igetitmusic.JIMS_Sonoflash.*"
               xmlns:audio="assets.audio.*"
               minWidth="365" minHeight="325"
               width="365" height="325" 
               viewSourceURL="srcview/index.html"
               applicationComplete="appCompleteHandler(event)"
               currentStateChange="{ctlBobInterval.value = 0}">    
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- Declarations                                                                -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    
    <fx:Declarations>
        <s:GlowFilter id="redGlowFilter" blurX="20" blurY="20" color="0xFF0000"/>
    </fx:Declarations>
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- States                                                                      -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    
    <s:states>
        <s:State name="start" stateGroups="bookends"/>
        <s:State name="foo"        stateGroups="kb, Res"/>
        <s:State name="stack"    stateGroups="kb, Res, P5s"/>
        <s:State name="fill"    stateGroups="kb, P5s, P8s, topNotes, bottomNotes"/>
        <s:State name="oct"        stateGroups="kb, topNotes, bottomNotes"/>
        <s:State name="kb1"        stateGroups="kb, topNotes, keyName"/>
        <s:State name="kb3"        stateGroups="kb, topNotes, keyName, notCentered"/>
        <s:State name="end"        stateGroups="bookends"/>
    </s:states>
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- Transitions                                                                 -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    
    <s:transitions>          
        <!-- start -->
        <s:Transition fromState="*" toState="start">
            <s:Sequence>
            </s:Sequence>
        </s:Transition>
        
        <!-- foo -->
        <s:Transition fromState="*" toState="foo">
            <s:Sequence>        
                <s:SetAction target="{Re0}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c01_consider_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c02_Re_MP3}"/>        
                <s:SetAction target="{ctlKeyword}" property="text" value="fiancé, résumé"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{true}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c03_likeFiance_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c04_toRemindYou_MP3}"/>
                <s:SetAction target="{ctlKeyword}" property="text" value="Ré = ''ray''"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c05_reAsRay_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c06_inLaterLessons_MP3}"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{false}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c07_earlier_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c08_littleNumber_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c09_octave_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c09b_fromReZero_MP3}"/>
                <s:SetAction target="{Re1}" property="visible"/>
                <s:SetAction target="{Re0ToRe1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c10_re1IsOneOctHigher_MP3}"/>
                <s:SetAction target="{Re_1}" property="visible"/>
                <s:SetAction target="{Re0ToRe_1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c11_andReMinusOne_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c12_nowIfAllYou_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c13_howeverByKnowing_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c14_thatOneAdditional_MP3}"/>    
                <s:SetAction target="{ctlKeyword}" property="text" value="the Fifth"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{true}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c15_theFifth_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- stack -->
        <s:Transition fromState="*" toState="stack">
            <s:Sequence>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c16_heresHow_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c17_firstWellAddANote_MP3}"/>
                <s:SetAction target="{La0}" property="visible"/>
                <s:SetAction target="{Re0ToLa0}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c20_one5thHigher_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c21a_wellCallThisNewNote_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c21b_la_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c22_theBlueArrowShows_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c23_nextWellAddANoteTwo_MP3}"/>
                <s:SetAction target="{Mi1}" property="visible"/>
                <s:SetAction target="{La0ToMi1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c24_two5thHigherThan_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c25a_andCallIt_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c25b_miWhichIsAFunnyWay_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c26_theAccentMarkOverTheI_MP3}"/>
                <s:SetAction target="{ctlKeyword}" property="text" value="Mí = ''mee''"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{true}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c27_miIsPronouncedMee_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c28_nextWellAddTwoNotes_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c29_twoNotesBelowReZero_MP3}"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{false}"/>
                <s:SetAction target="{So_1}" property="visible"/>
                <s:SetAction target="{Re0ToSo_1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c30_soOne5thLower_MP3}"/>
                <s:SetAction target="{Do_1}" property="visible"/>
                <s:SetAction target="{So_1ToDo_1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c31_andDo2FifthsLower_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c32_lookAtTheBlueArrows_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c33_eachPointsFromANote_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c34_higherFreqAreInOne_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c35a_andLowerFrequencies_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c35b_butAllOfTheseArrows_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c35c_theyShowTheConstantShape_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c36_thisStackOf5ths_MP3}"/>
                <s:SetAction target="{ctlKeyword}" property="text" value="Stack of Fifths"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{true}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c37_theStackOf5ths_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- fill -->
        <s:Transition fromState="*" toState="fill">
            <s:Sequence>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{false}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c38_nowWereGoingToFill_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c39_toDo_MP3}"/>
                <s:SetAction target="{Do0}" property="visible"/>
                <s:SetAction target="{Do_1ToDo0}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c40_wellAddTwoOctaves_MP3}"/>
                <s:SetAction target="{Do1}" property="visible"/>
                <s:SetAction target="{Do0ToDo1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c42_withTheirArrowsPointing_MP3}"/>
                <s:SetAction target="{So0}" property="visible"/>
                <s:SetAction target="{So_1ToSo0}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c43_wellAddOneOctave_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c44_resOctavesAreAlreadyInPlace_MP3}"/>
                <s:SetAction target="{La_1}" property="visible"/>
                <s:SetAction target="{La0ToLa_1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c45_lastlyWellAdd2OctBelowMi_MP3}"/>
                <s:SetAction target="{Mi0}" property="visible"/>
                <s:SetAction target="{Mi1ToMi0}" property="visible"/>
                <s:SetAction target="{Mi_1}" property="visible"/>
                <s:SetAction target="{Mi0ToMi_1}" property="visible"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c46_theResultIs2OctOf_MP3}"/>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{true}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c47_pentatonicScale_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- oct -->
        <s:Transition fromState="*" toState="oct">
            <s:Sequence>
                <s:SetAction target="{ctlKeyword}" property="visible" value="{false}"/>
                <s:Parallel>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c48a_theDoThats_MP3}"/>
                
                <s:AnimateFilter target="{Do0}"
                                 bitmapFilter="{redGlowFilter}"
                                 duration="250" 
                                 repeatCount="16"
                                 repeatBehavior="reverse">
                    <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                </s:AnimateFilter>
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c48b_doZeroAndItsOctavesAre_MP3}"/>
                
                <s:Parallel>
                    <s:Sequence>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c48c_do1AndDoMinus1_MP3}"/>
                    </s:Sequence>
                    
                    <s:AnimateFilter targets="{[Do_1, Do1]}"
                                     bitmapFilter="{redGlowFilter}"
                                     duration="250" 
                                     repeatCount="12"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                </s:Parallel>
                
                <s:Parallel>
                    <s:Sequence>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c49_allOfTheNotesBetweenDo0_MP3}"/>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c50_do1sFreqNotIncluding_MP3}"/>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c51a_do1sFreqArePartOf_MP3}"/>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c51b_octaveZero_MP3}"/>
                    </s:Sequence>                    
                    
                    <s:AnimateFilter targets="{[Do0, Re0, Mi0, So0, La0]}"
                                     bitmapFilter="{redGlowFilter}"
                                     duration="250" 
                                     repeatCount="32"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                </s:Parallel>
                
                <s:Parallel>
                    <s:Sequence>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c52_thoseBetweenDo0and_MP3}"/>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c53a_andDoMinus1_MP3}"/>
                        <mx:SoundEffect target="{this}" useDuration="false" source="{c53b_arePartOfOctaveMinusOne_MP3}"/>
                    </s:Sequence>                
                    
                    <s:AnimateFilter targets="{[Do_1, Re_1, Mi_1, So_1, La_1]}"
                                     bitmapFilter="{redGlowFilter}"
                                     duration="250" 
                                     repeatCount="24"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c54_octavesRunFrom_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c55a_doToDo_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c55b_andIncludeTheLowerDo_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c55c_butNotTheHigherDo_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- kb1 -->
        <s:Transition fromState="*" toState="kb1">
            <s:Sequence>
                <s:SetAction target="{macKB}" property="visible"/>
                
                <s:Parallel>                    
                    <s:Scale target="{grpKeyboard}" duration="1000"/>
                    <s:Move target="{grpKeyboard}" duration="1000"/>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c56_youCanUseYorComputerKB_MP3}"/>
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c57_toControlTheNotesOfThe_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- kb3 -->
        <s:Transition fromState="*" toState="kb3">
            <s:Sequence>
                <s:Parallel>                    
                    <s:Scale target="{grpKeyboard}" duration="500"/>
                    <s:Move target="{grpKeyboard}" duration="500"/>
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c59_behindEachNoteName_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c60_theWhiteLetterShows_MP3}"/>
                
                <s:Parallel>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c61_forExampleTheHBehindRe0_MP3}"/>
                    
                    <s:AnimateFilter target="{Re0}"
                                     bitmapFilter="{redGlowFilter}"
                                     duration="250" 
                                     repeatCount="16"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c62_allOfTheOtherNotes_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c63_exactlyAsTheyAppear_MP3}"/>
                
                <s:SetAction target="{grpBob}" property="visible"/>
                <s:SetAction target="{ctlRule}" property="visible"/>
                <s:Parallel>
                    <mx:SoundEffect target="{this}" useDuration="false" source="{c65_theSliderOnTheLeft_MP3}"/>
                    
                    <s:AnimateFilter target="{grpBob}"
                                     bitmapFilter="{redGlowFilter}"
                                     duration="250" 
                                     repeatCount="16"
                                     repeatBehavior="reverse">
                        <s:SimpleMotionPath property="alpha" valueFrom="0.2" valueTo="1"/>
                    </s:AnimateFilter>
                </s:Parallel>
                
                <mx:SoundEffect target="{this}" useDuration="false" source="{c66_whenItChanges_MP3}"/>
                <mx:SoundEffect target="{this}" useDuration="false" source="{c64_useYourComputerKeyboard_MP3}"/>
            </s:Sequence>
        </s:Transition>
        
        <!-- end -->
        <s:Transition fromState="*" toState="end"> 
            <s:Sequence>
            </s:Sequence>
        </s:Transition>
    </s:transitions>
    
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- Visual Elements                                                               -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    
    <s:Button horizontalCenter="0" y="105" label="Start Learning"
              click="{this.currentState='foo'}"
              includeIn="start"/>
    
    <s:Label id="ctlKeyword"
             visible="false"
             horizontalCenter="0" 
             verticalAlign="middle"
             textAlign="center" 
             fontSize="48"
             text.foo="the Fifth"
             text.fill="Pentatonic Scale"
             text.stack="Stack of Fifths"/>
    
    <s:RichText id="ctlDefinition" 
                visible="false"
                horizontalCenter="0" verticalCenter="-25"
                width="66%" height="30%"
                textAlign="center" verticalAlign="middle"
                fontStyle="italic" fontSize="24"/>
    
    <!-- Bob -->
    <s:Group id="grpBob"
             left="0" verticalCenter="0" 
             visible="false" visible.kb3="true"
             enabled="false" enabled.kb3="true"
             includeInLayout="true">
        
        <s:VSlider id="ctlBobInterval"
                   horizontalCenter="0" verticalCenter="0" height="80%"
                   minimum="{MIN_BOB}" maximum="{MAX_BOB}"
                   value="0"
                   snapInterval="100"
                   liveDragging="true"
                   change="ctlBobInterval_changeHandler(event);"
                   valueCommit="ctlBobInterval_valueCommitHandler(event);"/>
        
        <s:Label horizontalCenter="0" top="0" text="High" fontSize="12" textAlign="center"/>
        <s:Label horizontalCenter="0" bottom="0" text="Low" fontSize="12" textAlign="center"/>
    </s:Group>
    
    
    <mx:HRule id="ctlRule" 
              visible="false" visible.kb3="true"
              verticalCenter="{_bobsThumbHeight}" height="1" 
              left="{grpBob.width + 5}"
              width="{this.stage.width - (grpBob.width + grpKeyboard.width + 10)}"/>
    
    <s:BitmapImage id="macKB" horizontalCenter="0" top="0" height="232.8" width="500" source="@Embed('assets/images/macKeyboard.jpg')" visible="false" visible.kb1="true"/>
    
    <k:KeyboardGroup id="grpKeyboard"
         verticalCenter="{_bobsThumbHeight}" verticalCenter.kb1="-40"
         scaleX="1" scaleX.kb1="0.5"
         scaleY="1" scaleY.kb1="0.5"
         horizontalCenter="0" horizontalCenter.notCentered="{grpKeyboard.width/2}"
         clipAndEnableScrolling="true"
         visible.bookends="false" visible.kb="true">
        
        <k:layout>
            <k:WickiNoteLayout margin="5" octaves="2.5" octaves.keyName="2" cardinality="5"/>
        </k:layout>
        
        <k:NoteButton id="Do1" alphas="2" betas="-2"  keyName="6" keyCode="54" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true"/>        
        <k:NoteButton id="Re1" alphas="1" betas="0"  keyName="7" keyCode="55" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true" visible.Res="true"/>
        <k:NoteButton id="Mi1" alphas="0" betas="2"  keyName="8" keyCode="56" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true" visible.stack="true"/>
        
        <k:NoteButton id="So0" alphas="1" betas="-1"  keyName="Y" keyCode="89" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true"/>
        <k:NoteButton id="La0" alphas="0" betas="1"  keyName="U" keyCode="85" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true" visible.stack="true"/>
        
        <k:NoteButton id="Do0" alphas="1" betas="-2"  keyName="G" keyCode="71" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true"/>
        <k:NoteButton id="Re0" alphas="0" betas="0"  keyName="H" keyCode="72" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true" visible.Res="true"/>
        <k:NoteButton id="Mi0" alphas="-1" betas="2"  keyName="J" keyCode="74" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true"/>
        
        <k:NoteButton id="So_1" alphas="0" betas="-1" keyName="B" keyCode="66" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true" visible.stack="true"/>
        <k:NoteButton id="La_1" alphas="-1" betas="1" keyName="N" keyCode="78" showKeyName="false" showKeyName.keyName="true" skinClass="MacNoteButtonSkin" visible="false" visible.topNotes="true"/>
        
        <k:NoteButton id="Do_1" alphas="0" betas="-2"  showKeyName="false" skinClass="MacNoteButtonSkin" visible="false" visible.bottomNotes="true" visible.stack="true"/>
        <k:NoteButton id="Re_1" alphas="-1" betas="0"  showKeyName="false" skinClass="MacNoteButtonSkin" visible="false" visible.bottomNotes="true" visible.Res="true"/>
        <k:NoteButton id="Mi_1" alphas="-2" betas="2"  showKeyName="false" skinClass="MacNoteButtonSkin" visible="false" visible.bottomNotes="true"/>
        
        <!-- P8 arrows -->
        <k:KeyboardIntervalArrow id="Do_1ToDo0" fromNoteButton="{Do_1}" toNoteButton="{Do0}" visible="false" visible.P8s="true" showIntervalSymbol="false"/>        
        <k:KeyboardIntervalArrow id="Do0ToDo1" fromNoteButton="{Do0}" toNoteButton="{Do1}" visible="false" visible.P8s="true" showIntervalSymbol="false"/>    
        <k:KeyboardIntervalArrow id="So_1ToSo0" fromNoteButton="{So_1}" toNoteButton="{So0}" visible="false" visible.P8s="true" showIntervalSymbol="false"/>
        <k:KeyboardIntervalArrow id="Re0ToRe1" fromNoteButton="{Re0}" toNoteButton="{Re1}" visible="false" visible.Res="true" visible.fill="true" showIntervalSymbol="false"/>
        <k:KeyboardIntervalArrow id="Re0ToRe_1" fromNoteButton="{Re0}" toNoteButton="{Re_1}" visible="false" visible.Res="true" visible.fill="true" showIntervalSymbol="false"/>
        <k:KeyboardIntervalArrow id="La0ToLa_1" fromNoteButton="{La0}" toNoteButton="{La_1}" visible="false" visible.P8s="true" showIntervalSymbol="false"/>
        <k:KeyboardIntervalArrow id="Mi1ToMi0" fromNoteButton="{Mi1}" toNoteButton="{Mi0}" visible="false" visible.P8s="true" showIntervalSymbol="false"/>
        <k:KeyboardIntervalArrow id="Mi0ToMi_1" fromNoteButton="{Mi0}" toNoteButton="{Mi_1}" visible="false" visible.P8s="true" showIntervalSymbol="false"/>
        
        <!-- P5 arrows -->
        <k:KeyboardIntervalArrow id="Re0ToLa0" fromNoteButton="{Re0}" toNoteButton="{La0}" visible="false" visible.P5s="true" showIntervalSymbol="false"/>
        <k:KeyboardIntervalArrow id="La0ToMi1" fromNoteButton="{La0}" toNoteButton="{Mi1}" visible="false" visible.P5s="true" showIntervalSymbol="false"/>
        <k:KeyboardIntervalArrow id="Re0ToSo_1" fromNoteButton="{Re0}" toNoteButton="{So_1}" visible="false" visible.P5s="true" showIntervalSymbol="false"/>
        <k:KeyboardIntervalArrow id="So_1ToDo_1" fromNoteButton="{So_1}" toNoteButton="{Do_1}" visible="false" visible.P5s="true" showIntervalSymbol="false"/>
    </k:KeyboardGroup>
    
    <!-- Meta-controls -->
    <igimc:StateButtonBar id="ctlState" x="0" y="300" width="365" height="20"/>
    
    
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <!-- Code                                                                          -->
    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
    <fx:Script>
        <![CDATA[
            import com.igetitmusic.JIMS_Sonoflash.*;
            import com.igetitmusic.assert.Assert;
            import com.igetitmusic.music.Model;
            import com.igetitmusic.music.Note;
            import com.igetitmusic.synth.PingNoteSound;
            import com.igetitmusic.synth.Synth;
            
            import flash.media.*;
            
            import mx.events.FlexEvent;
            
            
            //--------------------------------------------------------------------------
            //
            //  Constants
            //
            //--------------------------------------------------------------------------
            
            private const CENTS_PER_OCTAVE:Number =  1200;            
            private const MAX_BOB:Number          =  CENTS_PER_OCTAVE;
            private const MIN_BOB:Number          = -MAX_BOB;
            
            //----------------------------------
            //  synth
            //----------------------------------
            
            public const synth:Synth = new Synth(Model.dataModel, PingNoteSound);            
            
            //--------------------------------------------------------------------------
            //
            //  Properties
            //
            //--------------------------------------------------------------------------
            
            //----------------------------------
            //  baseFrequency
            //----------------------------------
            
            private var baseFrequency:Number      =  440;        // 440Hz -- the A above middle C
            
            //----------------------------------
            //  bobSound
            //----------------------------------
            
            [Bindable]public var _bobSound:PingSound = new PingSound(440);
            public function get bobSound():PingSound { return _bobSound; }
            public function set bobSound(v:PingSound):void { _bobSound = v; }
            
            //----------------------------------
            //  bobsThumbHeight
            //----------------------------------
            
            // Suitable for use in MXML statement: verticalCenter="{_bobsThumbHeight}"
            [Bindable]private var _bobsThumbHeight:Number = NaN;            
            public function get bobsThumbHeight():Number { return _bobsThumbHeight; }
            public function set bobsThumbHeight(v:Number):void { _bobsThumbHeight = v; }
            
            //----------------------------------
            //  bobsThumbsCenterY
            //----------------------------------
            
            // Suitable for use in MXML statement: y="{_bobsThumbsCenterY - ctlID.height}"
            [Bindable]private var _bobsThumbsCenterY:Number = NaN;            
            public function get bobsThumbsCenterY():Number { return _bobsThumbsCenterY; }
            public function set bobsThumbsCenterY(v:Number):void { _bobsThumbsCenterY = v; }
            
            //--------------------------------------------------------------------------
            //
            //  Methods
            //
            //--------------------------------------------------------------------------
            
            //----------------------------------
            //  centsToHz
            //----------------------------------
            
            public function centsToHz(c:Number):Number {
                return (baseFrequency * Math.pow(2, (c/CENTS_PER_OCTAVE))); 
            }
            
            //----------------------------------
            //  updateBobsThumbHeight
            //----------------------------------
            
            // Called on any change to Bob's value (VALUE_COMMIT).
            public function updateBobsThumbHeight():void {
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval.track != null", ctlBobInterval.track != null);}
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval.thumb != null", ctlBobInterval.thumb != null);}
                CONFIG::DEBUG {Assert.assertTrue("grpBob != null", grpBob != null);}
                
                var trackRange:Number    = ctlBobInterval.maximum - ctlBobInterval.minimum;
                var normalized:Number    = (ctlBobInterval.value  - ctlBobInterval.minimum) / trackRange;
                
                bobsThumbsCenterY        = ((normalized - 0.0) * (ctlBobInterval.thumb.height - ctlBobInterval.track.height)) + grpBob.y;
                bobsThumbHeight            =  (normalized - 0.5) * (ctlBobInterval.thumb.height - ctlBobInterval.track.height);
            }
            
            //--------------------------------------------------------------------------
            //
            //  Event Handlers
            //
            //--------------------------------------------------------------------------
            
            //----------------------------------
            //  appCompleteHandler
            //----------------------------------
            
            protected function appCompleteHandler(event:FlexEvent):void    {
                stage.addEventListener(KeyboardEvent.KEY_DOWN, globalKeyHandler);
                stage.addEventListener(KeyboardEvent.KEY_UP, globalKeyHandler);
                
                updateBobsThumbHeight();
            }
            
            //----------------------------------
            //  globalKeyHandler
            //----------------------------------
            
            public function globalKeyHandler(e:KeyboardEvent):void {
                var b:NoteButton = (grpKeyboard as KeyboardGroup).childButtonWithKeyCode(e.keyCode);
                if (b == null) return;
                
                var n:Note = b.note;
                
                if (n == null) {
                    // not sure what to do here
                } else {
                    // b is a note-controlling button
                    var modelState:Boolean = Model.dataModel.getNoteOn(n);
                    var keyboardState:Boolean = (e.type == KeyboardEvent.KEY_DOWN);
                    
                    if (modelState != keyboardState) {                      
                        // Change the state of the dataModel, which will 
                        // notify its listeners of the change.
                        Model.dataModel.setNoteOn(n, keyboardState);
                    }
                }              
            }
            
            //----------------------------------
            //  ctlBobInterval_valueCommitHandler
            //----------------------------------
            
            // called whenever Bob's value changes for any reason (animation, user action, whatever)
            protected function ctlBobInterval_valueCommitHandler(event:Event):void {
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("bobSound != null", bobSound != null);}
                
                updateBobsThumbHeight();
                if (isNaN(ctlBobInterval.value)) return;
                
                // keep model's refFreq in sync w/ Bob's pitch, so that keyboard plays the right pitches
                bobSound.frequency = centsToHz(ctlBobInterval.value);
                Model.dataModel.refFreq = this.centsToHz(ctlBobInterval.value);
                
                // play bobSound()                
            }
            
            //----------------------------------
            //  ctlBobInterval_changeHandler
            //----------------------------------
            
            protected function ctlBobInterval_changeHandler(event:Event):void {
                CONFIG::DEBUG {Assert.assertTrue("ctlBobInterval != null", ctlBobInterval != null);}
                CONFIG::DEBUG {Assert.assertTrue("bobSound != null", bobSound != null);}
                
                updateBobsThumbHeight();
                if (isNaN(ctlBobInterval.value)) return;
                
                bobSound.frequency = centsToHz(ctlBobInterval.value);
            }
            
            //--------------------------------------------------------------------------
            //
            //  Embedded Assets
            //
            //--------------------------------------------------------------------------
            
            // Define a class name for each embedded asset, so that it can be referred to by name        
            [Embed("assets/audio/c01_consider.mp3")]
            public const c01_consider_MP3:Class;
            
            [Embed("assets/audio/c02_Re.mp3")]
            public const c02_Re_MP3:Class;
            
            [Embed("assets/audio/c03_likeFiance.mp3")]
            public const c03_likeFiance_MP3:Class;
            
            [Embed("assets/audio/c04_toRemindYou.mp3")]
            public const c04_toRemindYou_MP3:Class;
            
            [Embed("assets/audio/c05_reAsRay.mp3")]
            public const c05_reAsRay_MP3:Class;
            
            [Embed("assets/audio/c06_inLaterLessons.mp3")]
            public const c06_inLaterLessons_MP3:Class;
            
            [Embed("assets/audio/c07_earlier.mp3")]
            public const c07_earlier_MP3:Class;
            
            [Embed("assets/audio/c08_littleNumber.mp3")]
            public const c08_littleNumber_MP3:Class;
            
            [Embed("assets/audio/c09_octave.mp3")]
            public const c09_octave_MP3:Class;
            
            [Embed("assets/audio/c09b_fromReZero.mp3")]
            public const c09b_fromReZero_MP3:Class;
            
            [Embed("assets/audio/c10_re1IsOneOctHigher.mp3")]
            public const c10_re1IsOneOctHigher_MP3:Class;
            
            [Embed("assets/audio/c11_andReMinusOne.mp3")]
            public const c11_andReMinusOne_MP3:Class;
            
            [Embed("assets/audio/c12_nowIfAllYou.mp3")]
            public const c12_nowIfAllYou_MP3:Class;
            
            [Embed("assets/audio/c13_howeverByKnowing.mp3")]
            public const c13_howeverByKnowing_MP3:Class;
            
            [Embed("assets/audio/c14_thatOneAdditional.mp3")]
            public const c14_thatOneAdditional_MP3:Class;
            
            [Embed("assets/audio/c15_theFifth.mp3")]
            public const c15_theFifth_MP3:Class;
            
            [Embed("assets/audio/c16_heresHow.mp3")]
            public const c16_heresHow_MP3:Class;
            
            [Embed("assets/audio/c17_firstWellAddANote.mp3")]
            public const c17_firstWellAddANote_MP3:Class;
            
            [Embed("assets/audio/c20_one5thHigher.mp3")]
            public const c20_one5thHigher_MP3:Class;
            
            [Embed("assets/audio/c21a_wellCallThisNewNote.mp3")]
            public const c21a_wellCallThisNewNote_MP3:Class;
            
            [Embed("assets/audio/c21b_la.mp3")]
            public const c21b_la_MP3:Class;
            
            [Embed("assets/audio/c22_theBlueArrowShows.mp3")]
            public const c22_theBlueArrowShows_MP3:Class;
            
            [Embed("assets/audio/c23_nextWellAddANoteTwo.mp3")]
            public const c23_nextWellAddANoteTwo_MP3:Class;
            
            [Embed("assets/audio/c24_two5thHigherThan.mp3")]
            public const c24_two5thHigherThan_MP3:Class;
            
            [Embed("assets/audio/c25a_andCallIt.mp3")]
            public const c25a_andCallIt_MP3:Class;
            
            [Embed("assets/audio/c25b_miWhichIsAFunnyWay.mp3")]
            public const c25b_miWhichIsAFunnyWay_MP3:Class;
            
            [Embed("assets/audio/c26_theAccentMarkOverTheI.mp3")]
            public const c26_theAccentMarkOverTheI_MP3:Class;
            
            [Embed("assets/audio/c27_miIsPronouncedMee.mp3")]
            public const c27_miIsPronouncedMee_MP3:Class;
            
            [Embed("assets/audio/c28_nextWellAddTwoNotes.mp3")]
            public const c28_nextWellAddTwoNotes_MP3:Class;
            
            [Embed("assets/audio/c29_twoNotesBelowReZero.mp3")]
            public const c29_twoNotesBelowReZero_MP3:Class;
            
            [Embed("assets/audio/c30_soOne5thLower.mp3")]
            public const c30_soOne5thLower_MP3:Class;
            
            [Embed("assets/audio/c31_andDo2FifthsLower.mp3")]
            public const c31_andDo2FifthsLower_MP3:Class;
            
            [Embed("assets/audio/c32_lookAtTheBlueArrows.mp3")]
            public const c32_lookAtTheBlueArrows_MP3:Class;
            
            [Embed("assets/audio/c33_eachPointsFromANote.mp3")]
            public const c33_eachPointsFromANote_MP3:Class;
            
            [Embed("assets/audio/c34_higherFreqAreInOne.mp3")]
            public const c34_higherFreqAreInOne_MP3:Class;
            
            [Embed("assets/audio/c35a_andLowerFrequencies.mp3")]
            public const c35a_andLowerFrequencies_MP3:Class;
            
            [Embed("assets/audio/c35b_butAllOfTheseArrows.mp3")]
            public const c35b_butAllOfTheseArrows_MP3:Class;
            
            [Embed("assets/audio/c35c_theyShowTheConstantShape.mp3")]
            public const c35c_theyShowTheConstantShape_MP3:Class;
            
            [Embed("assets/audio/c36_thisStackOf5ths.mp3")]
            public const c36_thisStackOf5ths_MP3:Class;
            
            [Embed("assets/audio/c37_theStackOf5ths.mp3")]
            public const c37_theStackOf5ths_MP3:Class;
            
            [Embed("assets/audio/c38_nowWereGoingToFill.mp3")]
            public const c38_nowWereGoingToFill_MP3:Class;
            
            [Embed("assets/audio/c39_toDo.mp3")]
            public const c39_toDo_MP3:Class;
            
            [Embed("assets/audio/c40_wellAddTwoOctaves.mp3")]
            public const c40_wellAddTwoOctaves_MP3:Class;
            
            [Embed("assets/audio/c42_withTheirArrowsPointing.mp3")]
            public const c42_withTheirArrowsPointing_MP3:Class;
            
            [Embed("assets/audio/c43_wellAddOneOctave.mp3")]
            public const c43_wellAddOneOctave_MP3:Class;
            
            [Embed("assets/audio/c44_resOctavesAreAlreadyInPlace.mp3")]
            public const c44_resOctavesAreAlreadyInPlace_MP3:Class;
            
            [Embed("assets/audio/c45_lastlyWellAdd2OctBelowMi.mp3")]
            public const c45_lastlyWellAdd2OctBelowMi_MP3:Class;
            
            [Embed("assets/audio/c46_theResultIs2OctOf.mp3")]
            public const c46_theResultIs2OctOf_MP3:Class;
            
            [Embed("assets/audio/c47_pentatonicScale.mp3")]
            public const c47_pentatonicScale_MP3:Class;
            
            [Embed("assets/audio/c48a_theDoThats.mp3")]
            public const c48a_theDoThats_MP3:Class;
            
            [Embed("assets/audio/c48b_doZeroAndItsOctavesAre.mp3")]
            public const c48b_doZeroAndItsOctavesAre_MP3:Class;
            
            [Embed("assets/audio/c48c_do1AndDoMinus1.mp3")]
            public const c48c_do1AndDoMinus1_MP3:Class;
            
            [Embed("assets/audio/c49_allOfTheNotesBetweenDo0.mp3")]
            public const c49_allOfTheNotesBetweenDo0_MP3:Class;
            
            [Embed("assets/audio/c50_do1sFreqNotIncluding.mp3")]
            public const c50_do1sFreqNotIncluding_MP3:Class;
            
            [Embed("assets/audio/c51a_do1sFreqArePartOf.mp3")]
            public const c51a_do1sFreqArePartOf_MP3:Class;
            
            [Embed("assets/audio/c51b_octaveZero.mp3")]
            public const c51b_octaveZero_MP3:Class;
            
            [Embed("assets/audio/c52_thoseBetweenDo0and.mp3")]
            public const c52_thoseBetweenDo0and_MP3:Class;
            
            [Embed("assets/audio/c53a_andDoMinus1.mp3")]
            public const c53a_andDoMinus1_MP3:Class;
            
            [Embed("assets/audio/c53b_arePartOfOctaveMinusOne.mp3")]
            public const c53b_arePartOfOctaveMinusOne_MP3:Class;
            
            [Embed("assets/audio/c54_octavesRunFrom.mp3")]
            public const c54_octavesRunFrom_MP3:Class;
            
            [Embed("assets/audio/c55a_doToDo.mp3")]
            public const c55a_doToDo_MP3:Class;
            
            [Embed("assets/audio/c55b_andIncludeTheLowerDo.mp3")]
            public const c55b_andIncludeTheLowerDo_MP3:Class;
            
            [Embed("assets/audio/c55c_butNotTheHigherDo.mp3")]
            public const c55c_butNotTheHigherDo_MP3:Class;
            
            [Embed("assets/audio/c56_youCanUseYorComputerKB.mp3")]
            public const c56_youCanUseYorComputerKB_MP3:Class;
            
            [Embed("assets/audio/c57_toControlTheNotesOfThe.mp3")]
            public const c57_toControlTheNotesOfThe_MP3:Class;
            
            [Embed("assets/audio/c58_letsZoomIn.mp3")]
            public const c58_letsZoomIn_MP3:Class;
            
            [Embed("assets/audio/c59_behindEachNoteName.mp3")]
            public const c59_behindEachNoteName_MP3:Class;
            
            [Embed("assets/audio/c60_theWhiteLetterShows.mp3")]
            public const c60_theWhiteLetterShows_MP3:Class;
            
            [Embed("assets/audio/c61_forExampleTheHBehindRe0.mp3")]
            public const c61_forExampleTheHBehindRe0_MP3:Class;
            
            [Embed("assets/audio/c62_allOfTheOtherNotes.mp3")]
            public const c62_allOfTheOtherNotes_MP3:Class;
            
            [Embed("assets/audio/c63_exactlyAsTheyAppear.mp3")]
            public const c63_exactlyAsTheyAppear_MP3:Class;
            
            [Embed("assets/audio/c64_useYourComputerKeyboard.mp3")]
            public const c64_useYourComputerKeyboard_MP3:Class;
            
            [Embed("assets/audio/c65_theSliderOnTheLeft.mp3")]
            public const c65_theSliderOnTheLeft_MP3:Class;
            
            [Embed("assets/audio/c66_whenItChanges.mp3")]
            public const c66_whenItChanges_MP3:Class;
            
            [Embed("assets/audio/c67_romDo0ToRe0IsAlways.mp3")]
            public const c67_romDo0ToRe0IsAlways_MP3:Class;
            
            [Embed("assets/audio/c68_2FifthsUp.mp3")]
            public const c68_2FifthsUp_MP3:Class;
            
            [Embed("assets/audio/c69_and1OctDown.mp3")]
            public const c69_and1OctDown_MP3:Class;
            
            [Embed("assets/audio/c70_fromRe0toMi1IsAlways.mp3")]
            public const c70_fromRe0toMi1IsAlways_MP3:Class;
            
            [Embed("assets/audio/c71_two5thsUp.mp3")]
            public const c71_two5thsUp_MP3:Class;
            
            [Embed("assets/audio/c72_andSoOn.mp3")]
            public const c72_andSoOn_MP3:Class;
            
            [Embed("assets/audio/c73_useYourComputerKeyboard.mp3")]
            public const c73_useYourComputerKeyboard_MP3:Class;
        ]]>
    </fx:Script>
</s:Application>