# Solfege - free ear training software
# Copyright (C) 2007, 2008 Tom Cato Amundsen
# License is GPL, see file COPYING

import unittest
import mpd
from mpd.track import Track, MidiEventStream
from mpd.rat import Rat
from src import lessonfile
from src import cfg

class TestTrack(unittest.TestCase):
    def test_simple1(self):
        t = Track()
        t.note(4, 90, 127)
        self.assertEquals(list(MidiEventStream(t)),
          [('program-change', 0, 0),
           ('note-on', 0, 90, 127),
           ('notelen-time', Rat(1, 4)),
           ('note-off', 0, 90, 127)])
    def test_1voice_setpatch(self):
        t = Track()
        t.note(4, 90, 127)
        t.set_patch(3)
        t.note(4, 91, 127)
        self.assertEquals(list(MidiEventStream(t)),
          [('program-change', 0, 0),
           ('note-on', 0, 90, 127),
           ('notelen-time', Rat(1, 4)),
           ('note-off', 0, 90, 127),
           ('program-change', 0, 3),
           ('note-on', 0, 91, 127),
           ('notelen-time', Rat(1, 4)),
           ('note-off', 0, 91, 127),
           ])

class TestMidiEventStream(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', True)
    def test_track1(self):
        t = Track()
        t.prepend_patch(33)
        t.note(4, 60, 120)
    def test_3instr(self):
        t1 = Track()
        t1.set_patch(3)
        t1.note(4, 93, 127)
        t2 = Track()
        t2.set_patch(4)
        t2.note(4, 94, 127)
        t3 = Track()
        t3.set_patch(5)
        t3.note(4, 95, 127)
        self.assertEquals(list(MidiEventStream(t1, t2, t3)),
           [('program-change', 0, 3),
            ('note-on', 0, 93, 127),
            ('program-change', 1, 4),
            ('note-on', 1, 94, 127),
            ('program-change', 2, 5),
            ('note-on', 2, 95, 127),
            ('notelen-time', Rat(1, 4)),
            ('note-off', 0, 93, 127),
            ('note-off', 1, 94, 127),
            ('note-off', 2, 95, 127)])
        self.assertEquals(MidiEventStream(t1, t2, t3).str_repr(details=1),
            "p0:3 p1:4 p2:5 n0:93 n1:94 n2:95 d1/4 o93 o94 o95")
    def test_track2(self):
        self.p = lessonfile.QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = music("\staff{ c'' }"
                                + "\\addvoice{ e' }"
                                + "\staff{ c }")
        }
        """)
        self.p._idx = 0
        instrument = self.p.prepare_instrument_list(self.p.get_question())
        if len(instrument) == 2:
            instrument = instrument * 3
        # music_to_tracklist is not complete.
        tracklist = mpd.music_to_tracklist(self.p.get_question()['music'].get_mpd_music_string(self.p), instrument[1])
    def test_track3(self):
        self.p = lessonfile.QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = music("\staff{ c''1 c''1 }"
                                + "\\addvoice{ r4 e'2. e'1 }"
                                + "\staff{ r4 r g2 g1 }"
                                + "\\addvoice{ r4 r r c c1}")
        }
        """)
        self.p._idx = 0
        instrument = self.p.prepare_instrument_list(self.p.get_question())
        self.assertEquals(len(instrument), 6)
        # music_to_tracklist is not complete.
        tracklist = mpd.music_to_tracklist(self.p.get_question()['music'].get_mpd_music_string(self.p), instrument[1])
        track_fasit = ["n72 d1/1 o72 n72 d1/1 o72",
                       "d1/4 n64 d3/4 o64 n64 d1/1 o64",
                       "d1/2 n55 d1/2 o55 n55 d1/1 o55",
                       "d3/4 n48 d1/4 o48 n48 d1/1 o48"]
        for idx, correct in enumerate(track_fasit):
            self.assertEquals(tracklist[idx].str_repr(), correct)
        for idx in range(4):
            tracklist[idx].prepend_patch(idx + 1)
            track_fasit[idx] = "p%i " % (idx + 1) + track_fasit[idx]
        for idx, correct in enumerate(track_fasit):
            self.assertEquals(tracklist[idx].str_repr(), correct)
        self.assertEquals(MidiEventStream(*tracklist).str_repr(details=1),
          "p0:1 n0:72 d1/4 "
          "p1:2 n1:64 d1/4 "
          "p2:3 n2:55 d1/4 "
          "p3:4 n3:48 d1/4 "
          "o48 o55 o64 o72 "
          "n0:72 n1:64 n2:55 n3:48 d1/1 "
          "o48 o55 o64 o72")
    def test_track3_1(self):
        self.p = lessonfile.QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = music("\staff{ c''1 c''1 }"
                                + "\staff{ r4 r g2 g1 }")
        }
        """)
        self.p._idx = 0
        instrument = self.p.prepare_instrument_list(self.p.get_question())
        self.assertEquals(len(instrument), 6)
        # music_to_tracklist is not complete.
        tracklist = mpd.music_to_tracklist(self.p.get_question()['music'].get_mpd_music_string(self.p), instrument[1])
        track_fasit = ["n72 d1/1 o72 n72 d1/1 o72",
                       "d1/2 n55 d1/2 o55 n55 d1/1 o55"]
        for idx, correct in enumerate(track_fasit):
            self.assertEquals(tracklist[idx].str_repr(), correct)
        for idx in range(2):
            tracklist[idx].prepend_patch(idx + 1)
            track_fasit[idx] = "p%i " % (idx + 1) + track_fasit[idx]
        for idx, correct in enumerate(track_fasit):
            self.assertEquals(tracklist[idx].str_repr(), correct)
        self.assertEquals(MidiEventStream(*tracklist).str_repr(details=1),
          "p0:1 n0:72 d1/2 p1:2 n1:55 d1/2 o55 o72 n0:72 n1:55 d1/1 o55 o72")
    def test_track3_2(self):
        self.p = lessonfile.QuestionsLessonfile()
        self.p.parse_string(r"""
        header { random_transpose = no }
        question { music = music("\staff{ c''1 c''1 }"
                                + "\staff{ r4 r g2 g1 }"
                                + "\staff{ r4 r r c c1}")
        }
        """)
        self.p._idx = 0
        instrument = self.p.prepare_instrument_list(self.p.get_question())
        self.assertEquals(len(instrument), 6)
        # music_to_tracklist is not complete.
        tracklist = mpd.music_to_tracklist(self.p.get_question()['music'].get_mpd_music_string(self.p), instrument[1])
        track_fasit = ["n72 d1/1 o72 n72 d1/1 o72",
                       "d1/2 n55 d1/2 o55 n55 d1/1 o55",
                       "d3/4 n48 d1/4 o48 n48 d1/1 o48"]
        for idx, correct in enumerate(track_fasit):
            self.assertEquals(tracklist[idx].str_repr(), correct)
        for idx in range(3):
            tracklist[idx].prepend_patch(idx + 1)
            track_fasit[idx] = "p%i " % (idx + 1) + track_fasit[idx]
        for idx, correct in enumerate(track_fasit):
            self.assertEquals(tracklist[idx].str_repr(), correct)
        self.assertEquals(MidiEventStream(*tracklist).str_repr(details=1),
          "p0:1 n0:72 d1/2 "
          "p1:2 n1:55 d1/4 "
          "p2:3 n2:48 d1/4 "
          "o48 o55 o72 "
          "n0:72 n1:55 n2:48 d1/1 "
          "o48 o55 o72")


suite = unittest.makeSuite(TestTrack)
suite.addTest(unittest.makeSuite(TestMidiEventStream))

