import unittest import os import sys import time import pygame import pygame.midi import pygame.compat from pygame.locals import * class MidiInputTest(unittest.TestCase): def setUp(self): pygame.midi.init() in_id = pygame.midi.get_default_input_id() if in_id != -1: self.midi_input = pygame.midi.Input(in_id) else: self.midi_input = None def tearDown(self): if self.midi_input: self.midi_input.close() pygame.midi.quit() def test_Input(self): """|tags: interactive| """ i = pygame.midi.get_default_input_id() if self.midi_input: self.assertEqual(self.midi_input.device_id, i) # try feeding it an input id. i = pygame.midi.get_default_output_id() # can handle some invalid input too. self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, i) self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, 9009) self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, -1) self.assertRaises(TypeError, pygame.midi.Input, "1234") self.assertRaises(OverflowError, pygame.midi.Input, pow(2, 99)) def test_poll(self): if not self.midi_input: self.skipTest('No midi Input device') self.assertFalse(self.midi_input.poll()) # TODO fake some incoming data pygame.midi.quit() self.assertRaises(RuntimeError, self.midi_input.poll) # set midi_input to None to avoid error in tearDown self.midi_input = None def test_read(self): if not self.midi_input: self.skipTest('No midi Input device') read = self.midi_input.read(5) self.assertEqual(read, []) # TODO fake some incoming data pygame.midi.quit() self.assertRaises(RuntimeError, self.midi_input.read, 52) # set midi_input to None to avoid error in tearDown self.midi_input = None def test_close(self): if not self.midi_input: self.skipTest('No midi Input device') self.assertIsNotNone(self.midi_input._input) self.midi_input.close() self.assertIsNone(self.midi_input._input) class MidiOutputTest(unittest.TestCase): def setUp(self): pygame.midi.init() m_out_id = pygame.midi.get_default_output_id() if m_out_id != -1: self.midi_output = pygame.midi.Output(m_out_id) else: self.midi_output = None def tearDown(self): if self.midi_output: self.midi_output.close() pygame.midi.quit() def test_Output(self): """|tags: interactive| """ i = pygame.midi.get_default_output_id() if self.midi_output: self.assertEqual(self.midi_output.device_id, i) # try feeding it an input id. i = pygame.midi.get_default_input_id() # can handle some invalid input too. self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, i) self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, 9009) self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, -1) self.assertRaises(TypeError, pygame.midi.Output,"1234") self.assertRaises(OverflowError, pygame.midi.Output, pow(2,99)) def test_note_off(self): """|tags: interactive| """ if self.midi_output: out = self.midi_output out.note_on(5, 30, 0) out.note_off(5, 30, 0) with self.assertRaises(ValueError) as cm: out.note_off(5, 30, 25) self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") with self.assertRaises(ValueError) as cm: out.note_off(5, 30, -1) self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") def test_note_on(self): """|tags: interactive| """ if self.midi_output: out = self.midi_output out.note_on(5, 30, 0) out.note_on(5, 42, 10) with self.assertRaises(ValueError) as cm: out.note_on(5, 30, 25) self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") with self.assertRaises(ValueError) as cm: out.note_on(5, 30, -1) self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") def test_set_instrument(self): if not self.midi_output: self.skipTest('No midi device') out = self.midi_output out.set_instrument(5) out.set_instrument(42, channel=2) with self.assertRaises(ValueError) as cm: out.set_instrument(-6) self.assertEqual(str(cm.exception), "Undefined instrument id: -6") with self.assertRaises(ValueError) as cm: out.set_instrument(156) self.assertEqual(str(cm.exception), "Undefined instrument id: 156") with self.assertRaises(ValueError) as cm: out.set_instrument(5, -1) self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") with self.assertRaises(ValueError) as cm: out.set_instrument(5, 16) self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") def test_write(self): if not self.midi_output: self.skipTest('No midi device') out = self.midi_output out.write([[[0xc0, 0, 0], 20000]]) # is equivalent to out.write([[[0xc0], 20000]]) # example from the docstring : # 1. choose program change 1 at time 20000 and # 2. send note 65 with velocity 100 500 ms later out.write([ [[0xc0, 0, 0], 20000], [[0x90, 60, 100], 20500] ]) out.write([]) verrry_long = [[[0x90, 60, i % 100], 20000 + 100 * i] for i in range(1024)] out.write(verrry_long) too_long = [[[0x90, 60, i % 100], 20000 + 100 * i] for i in range(1025)] self.assertRaises(IndexError, out.write, too_long) # test wrong data with self.assertRaises(TypeError) as cm: out.write('Non sens ?') error_msg = "unsupported operand type(s) for &: 'str' and 'int'" self.assertEqual(str(cm.exception), error_msg) with self.assertRaises(TypeError) as cm: out.write(["Hey what's that?"]) self.assertEqual(str(cm.exception), error_msg) def test_write_short(self): """|tags: interactive| """ if not self.midi_output: self.skipTest('No midi device') out = self.midi_output # program change out.write_short(0xc0) # put a note on, then off. out.write_short(0x90, 65, 100) out.write_short(0x80, 65, 100) out.write_short(0x90) def test_write_sys_ex(self): if not self.midi_output: self.skipTest('No midi device') out = self.midi_output out.write_sys_ex(pygame.midi.time(), [0xF0, 0x7D, 0x10, 0x11, 0x12, 0x13, 0xF7]) def test_pitch_bend(self): # FIXME : pitch_bend in the code, but not in documentation if not self.midi_output: self.skipTest('No midi device') out = self.midi_output with self.assertRaises(ValueError) as cm: out.pitch_bend(5, channel=-1) self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") with self.assertRaises(ValueError) as cm: out.pitch_bend(5, channel=16) with self.assertRaises(ValueError) as cm: out.pitch_bend(-10001, 1) self.assertEqual(str(cm.exception), "Pitch bend value must be between " "-8192 and +8191, not -10001.") with self.assertRaises(ValueError) as cm: out.pitch_bend(10665, 2) def test_close(self): if not self.midi_output: self.skipTest('No midi device') self.assertIsNotNone(self.midi_output._output) self.midi_output.close() self.assertIsNone(self.midi_output._output) def test_abort(self): if not self.midi_output: self.skipTest('No midi device') self.assertEqual(self.midi_output._aborted, 0) self.midi_output.abort() self.assertEqual(self.midi_output._aborted, 1) class MidiModuleTest(unittest.TestCase): def setUp(self): pygame.midi.init() def tearDown(self): pygame.midi.quit() def test_MidiException(self): def raiseit(): raise pygame.midi.MidiException('Hello Midi param') with self.assertRaises(pygame.midi.MidiException) as cm: raiseit() self.assertEqual(cm.exception.parameter, 'Hello Midi param') def test_get_count(self): c = pygame.midi.get_count() self.assertIsInstance(c, int) self.assertTrue(c >= 0) def test_get_default_input_id(self): midin_id = pygame.midi.get_default_input_id() # if there is a not None return make sure it is an int. self.assertIsInstance(midin_id, int) self.assertTrue(midin_id >= -1) pygame.midi.quit() self.assertRaises(RuntimeError, pygame.midi.get_default_output_id) def test_get_default_output_id(self): c = pygame.midi.get_default_output_id() self.assertIsInstance(c, int) self.assertTrue(c >= -1) pygame.midi.quit() self.assertRaises(RuntimeError, pygame.midi.get_default_output_id) def test_get_device_info(self): an_id = pygame.midi.get_default_output_id() if an_id != -1: interf, name, input, output, opened = pygame.midi.get_device_info(an_id) self.assertEqual(output, 1) self.assertEqual(input, 0) self.assertEqual(opened, 0) an_in_id = pygame.midi.get_default_input_id() if an_in_id != -1: r = pygame.midi.get_device_info(an_in_id) # if r is None, it means that the id is out of range. interf, name, input, output, opened = r self.assertEqual(output, 0) self.assertEqual(input, 1) self.assertEqual(opened, 0) out_of_range = pygame.midi.get_count() for num in range(out_of_range): self.assertIsNotNone(pygame.midi.get_device_info(num)) info = pygame.midi.get_device_info(out_of_range) self.assertIsNone(info) def test_init(self): pygame.midi.quit() self.assertRaises(RuntimeError, pygame.midi.get_count) # initialising many times should be fine. pygame.midi.init() pygame.midi.init() pygame.midi.init() pygame.midi.init() self.assertTrue(pygame.midi.get_init()) def test_midis2events(self): midi_data = ([[0xc0, 0, 1, 2], 20000], [[0x90, 60, 100, 'blablabla'], 20000] ) events = pygame.midi.midis2events(midi_data, 2) self.assertEqual(len(events), 2) for eve in events: # pygame.event.Event is a function, but ... self.assertEqual(eve.__class__.__name__, 'Event') self.assertEqual(eve.vice_id, 2) # FIXME I don't know what we want for the Event.timestamp # For now it accepts it accepts int as is: self.assertIsInstance(eve.timestamp, int) self.assertEqual(eve.timestamp, 20000) self.assertEqual(events[1].data3, 'blablabla') def test_quit(self): # It is safe to call this more than once. pygame.midi.quit() pygame.midi.init() pygame.midi.quit() pygame.midi.quit() pygame.midi.init() pygame.midi.init() pygame.midi.quit() self.assertFalse(pygame.midi.get_init()) def test_get_init(self): # Already initialized as pygame.midi.init() was called in setUp(). self.assertTrue(pygame.midi.get_init()) def test_time(self): mtime = pygame.midi.time() self.assertIsInstance(mtime, int) # should be close to 2-3... since the timer is just init'd. self.assertTrue(0 <= mtime < 100) def test_conversions(self): """ of frequencies to midi note numbers and ansi note names. """ from pygame.midi import ( frequency_to_midi, midi_to_frequency, midi_to_ansi_note ) self.assertEqual(frequency_to_midi(27.5), 21) self.assertEqual(frequency_to_midi(36.7), 26) self.assertEqual(frequency_to_midi(4186.0), 108) self.assertEqual(midi_to_frequency(21), 27.5) self.assertEqual(midi_to_frequency(26), 36.7) self.assertEqual(midi_to_frequency(108), 4186.0) self.assertEqual(midi_to_ansi_note(21), 'A0') self.assertEqual(midi_to_ansi_note(102), 'F#7') self.assertEqual(midi_to_ansi_note(108), 'C8') if __name__ == '__main__': unittest.main()