Lenard Lindstrom avatar Lenard Lindstrom committed 6c50402

implement *_tags.py module replacement to *_test.py level tags.
Now tests for unbuilt modules can be more easily skipped.
Also the IGNORE and SUBPROCESS_IGNORE black lists in
test/__init__.py goes away, replaced with *_tags.py tags.

Comments (0)

Files changed (24)

examples/arraydemo.py

     from pygame import surfarray
     from pygame.locals import *
 except ImportError:
-    raise ImportError, 'Error Importing Pygame/surfarray'
+    raise ImportError('Error Importing Pygame/surfarray')
 
 main_dir = os.path.split(os.path.abspath(__file__))[0]
 
         elif 'numeric' in surfarray.get_arraytype():
             surfarray.use_arraytype('numeric')
         else:
-            raise ImportError, 'No array package is installed'
+            raise ImportError('No array package is installed')
     else:
         surfarray.use_arraytype(arraytype)
 
         from Numeric import Int32 as int32
 
     pygame.init()
-    print 'Using', surfarray.get_arraytype().capitalize()
-    print 'Press the mouse button to advance image.'
-    print 'Press the "s" key to save the current image.'
+    print ('Using %s' % surfarray.get_arraytype().capitalize())
+    print ('Press the mouse button to advance image.')
+    print ('Press the "s" key to save the current image.')
 
     def surfdemo_show(array_img, name):
         "displays a surface, waits for user to continue"
                 #pygame.image.save(s, name+'.tga')
                 pygame.image.save(screen, name+'.png')
             elif e.type == QUIT:
-                raise SystemExit
+                raise SystemExit()
 
     #allblack
     allblack = N.zeros((128, 128), int32)
     pygame.quit()
 
 def usage():
-    print "Usage: command line option [--numpy|--numeric]"
-    print "  The default is to use NumPy if installed,"
-    print "  otherwise Numeric"
+    print ("Usage: command line option [--numpy|--numeric]")
+    print ("  The default is to use NumPy if installed,")
+    print ("  otherwise Numeric")
 
 if __name__ == '__main__':
     if len(sys.argv) == 2:

examples/camera.py

 
            self.get_and_flip()
            self.clock.tick()
-           print self.clock.get_fps()
+           print (self.clock.get_fps())
 
 def main():
     pygame.init()

examples/glcube.py

     from OpenGL.GL import *
     from OpenGL.GLU import *
 except:
-    print 'The GLCUBE example requires PyOpenGL'
+    print ('The GLCUBE example requires PyOpenGL')
     raise SystemExit
 
 
-"""Contains an example of midi input, and a separate example of midi output.
-
-By default it runs the output example.
-python midi.py --output
-python midi.py --input
-
-"""
-
-import sys
-import os
-
-import pygame
-import pygame.midi
-from pygame.locals import *
-
-try:  # Ensure set available for output example
-    set
-except NameError:
-    from sets import Set as set
-
-
-def print_device_info():
-    for i in range( pygame.midi.get_count() ):
-        r = pygame.midi.get_device_info(i)
-        (interf, name, input, output, opened) = r
-
-        in_out = ""
-        if input:
-            in_out = "(input)"
-        if output:
-            in_out = "(output)"
-
-        print ("%2i: interface :%s:, name :%s:, opened :%s:  %s" %
-               (i, interf, name, opened, in_out))
-        
-
-
-
-def input_main(device_id = None):
-    pygame.init()
-    pygame.fastevent.init()
-    event_get = pygame.fastevent.get
-    event_post = pygame.fastevent.post
-
-    pygame.midi.init()
-
-    print_device_info()
-
-
-    if device_id is None:
-        input_id = pygame.midi.get_default_input_device_id()
-    else:
-        input_id = device_id
-
-    print "using input_id :%s:" % input_id 
-    i = pygame.midi.Input( input_id )
-
-    pygame.display.set_mode((1,1))
-
-
-
-    going = True
-    while going:
-        events = event_get()
-        for e in events:
-            if e.type in [QUIT]:
-                going = False
-            if e.type in [KEYDOWN]:
-                going = False
-            if e.type in [pygame.midi.MIDIIN]:
-                print e
-
-        if i.poll():
-            midi_events = i.read(10)
-            # convert them into pygame events.
-            midi_evs = pygame.midi.midis2events(midi_events, i.device_id)
-
-            for m_e in midi_evs:
-                event_post( m_e )
-
-    del i
-    pygame.midi.quit()
-
-
-
-def output_main(device_id = None):
-    """Execute a musical keyboard example for the Church Organ instrument
-
-    This is a piano keyboard example, with a two octave keyboard, starting at
-    note F3. Left mouse down over a key starts a note, left up stops it. The
-    notes are also mapped to the computer keyboard keys, assuming an American
-    English PC keyboard (sorry everyone else, but I don't know if I can map to
-    absolute key position instead of value.) The white keys are on the second
-    row, TAB to BACKSLASH, starting with note F3. The black keys map to the top
-    row, '1' to BACKSPACE, starting with F#3. 'r' is middle C. Close the
-    window or pressing ESCAPE to quit the program. Key velocity (note
-    amplitude) varies vertically on the keyboard image, with minimum velocity
-    at the top of a key and maximum velocity at bottom.
-
-    Midi output is to the default midi output device for the computer.
-    
-    """
-
-    # A note to new pygamers:
-    #
-    # All the midi module stuff is in this function. It is unnecessary to
-    # understand how the keyboard display works to appreciate how midi
-    # messages are sent.
-
-    # The keyboard is drawn by a Keyboard instance. This instance maps Midi
-    # notes to musical keyboard keys. A regions surface maps window position
-    # to (Midi note, velocity) pairs. A key_mapping dictionary does the same
-    # for computer keyboard keys. Midi sound is controlled with direct method
-    # calls to a pygame.midi.Output instance.
-    #
-    # Things to consider when using pygame.midi:
-    #
-    # 1) Initialize the midi module with a to pygame.midi.init().
-    # 2) Create a midi.Output instance for the desired output device port.
-    # 3) Select instruments with set_instrument() method calls.
-    # 4) Play notes with note_on() and note_off() method calls.
-    # 5) Call pygame.midi.Quit() when finished. Though the midi module tries
-    #    to ensure that midi is properly shut down, it is best to do it
-    #    explicitly. A try/finally statement is the safest way to do this.
-    #
-    GRAND_PIANO = 0
-    CHURCH_ORGAN = 19
-
-    instrument = CHURCH_ORGAN
-    #instrument = GRAND_PIANO
-    start_note = 53  # F3 (white key note), start_note != 0
-    n_notes = 24  # Two octaves (14 white keys)
-    
-    bg_color = Color('slategray')
-
-    key_mapping = make_key_mapping([K_TAB, K_1, K_q, K_2, K_w, K_3, K_e, K_r,
-                                    K_5, K_t, K_6, K_y, K_u, K_8, K_i, K_9,
-                                    K_o, K_0, K_p, K_LEFTBRACKET, K_EQUALS,
-                                    K_RIGHTBRACKET, K_BACKSPACE, K_BACKSLASH],
-                                   start_note)
-    
-
-
-    pygame.init()
-    pygame.midi.init()
-
-    print_device_info()
-
-    if device_id is None:
-        port = pygame.midi.get_default_output_device_id()
-    else:
-        port = device_id
-
-    print "using output_id :%s:" % port
-
-
-
-    midi_out = pygame.midi.Output(port, 0)
-    try:
-        midi_out.set_instrument(instrument)
-        keyboard = Keyboard(start_note, n_notes)
-
-        screen = pygame.display.set_mode(keyboard.rect.size)
-        screen.fill(bg_color)
-        pygame.display.flip()
-
-        background = pygame.Surface(screen.get_size())
-        background.fill(bg_color)
-        dirty_rects = []
-        keyboard.draw(screen, background, dirty_rects)
-        pygame.display.update(dirty_rects)
-
-        regions = pygame.Surface(screen.get_size())  # initial color (0,0,0)
-        keyboard.map_regions(regions)
-
-        pygame.event.set_blocked(MOUSEMOTION)
-        repeat = 1
-        mouse_note = 0
-        on_notes = set()
-        while 1:
-            update_rects = None
-            e = pygame.event.wait()
-            if e.type == pygame.MOUSEBUTTONDOWN:
-                mouse_note, velocity, __, __  = regions.get_at(e.pos)
-                if mouse_note and mouse_note not in on_notes:
-                    keyboard.key_down(mouse_note)
-                    midi_out.note_on(mouse_note, velocity)
-                    on_notes.add(mouse_note)
-                else:
-                    mouse_note = 0
-            elif e.type == pygame.MOUSEBUTTONUP:
-                if mouse_note:
-                    midi_out.note_off(mouse_note)
-                    keyboard.key_up(mouse_note)
-                    on_notes.remove(mouse_note)
-                    mouse_note = 0
-            elif e.type == pygame.QUIT:
-                break
-            elif e.type == pygame.KEYDOWN:
-                if e.key == pygame.K_ESCAPE:
-                    break
-                try:
-                    note, velocity = key_mapping[e.key]
-                except KeyError:
-                    pass
-                else:
-                    if note not in on_notes:
-                        keyboard.key_down(note)
-                        midi_out.note_on(note, velocity)
-                        on_notes.add(note)
-            elif e.type == pygame.KEYUP:
-                try:
-                    note, __ = key_mapping[e.key]
-                except KeyError:
-                    pass
-                else:
-                    if note in on_notes and note != mouse_note:
-                        keyboard.key_up(note)
-                        midi_out.note_off(note, 0)
-                        on_notes.remove(note)
-
-            dirty_rects = []
-            keyboard.draw(screen, background, dirty_rects)
-            pygame.display.update(dirty_rects)
-    finally:
-        del midi_out
-        pygame.midi.quit()
-
-def make_key_mapping(key_list, start_note):
-    """Return a dictionary of (note, velocity) by computer keyboard key code"""
-    
-    mapping = {}
-    for i in range(len(key_list)):
-        mapping[key_list[i]] = (start_note + i, 127)
-    return mapping
-
-class NullKey(object):
-    """A dummy key that ignores events passed to it by other keys
-
-    A NullKey instance is the left key instance used by default
-    for the left most keyboard key.
-
-    """
-    
-    def _right_white_down(self):
-        pass
-
-    def _right_white_up(self):
-        pass
-
-    def _right_black_down(self):
-        pass
-
-    def _right_black_up(self):
-        pass
-
-null_key = NullKey()
-
-def key_class(updates, image_strip, image_rects, is_white_key=True):
-    """Return a keyboard key widget class
-
-    Arguments:
-    updates - a set into which a key instance adds itself if it needs
-        redrawing.
-    image_strip - The surface containing the images of all key states.
-    image_rects - A list of Rects giving the regions within image_strip that
-        are relevant to this key class.
-    is_white_key (default True) - Set false if this is a black key.
-
-    This function automates the creation of a key widget class for the
-    three basic key types. A key has two basic states, up or down (
-    depressed). Corresponding up and down images are drawn for each
-    of these two states. But to give the illusion of depth, a key
-    may have shadows cast upon it by the adjacent keys to its right.
-    These shadows change depending on the up/down state of the key and
-    its neighbors. So a key may support multiple images and states
-    depending on the shadows. A key type is determined by the length
-    of image_rects and the value of is_white.
-
-    """
-
-    # Naming convention: Variables used by the Key class as part of a
-    # closure start with 'c_'.
-
-    # State logic and shadows:
-    #
-    # A key may cast a shadow upon the key to its left. A black key casts a
-    # shadow on an adjacent white key. The shadow changes depending of whether
-    # the black or white key is depressed. A white key casts a shadow on the
-    # white key to its left if it is up and the left key is down. Therefore
-    # a keys state, and image it will draw, is determined entirely by its
-    # itself and the key immediately adjacent to it on the right. A white key
-    # is always assumed to have an adjacent white key.
-    #
-    # There can be up to eight key states, representing all permutations
-    # of the three fundamental states of self up/down, adjacent white
-    # right up/down, adjacent black up/down.
-    # 
-    down_state_none = 0
-    down_state_self = 1
-    down_state_white = down_state_self << 1
-    down_state_self_white = down_state_self | down_state_white
-    down_state_black = down_state_white << 1
-    down_state_self_black = down_state_self | down_state_black
-    down_state_white_black = down_state_white | down_state_black
-    down_state_all = down_state_self | down_state_white_black
-
-    # Some values used in the class.
-    #
-    c_down_state_initial = down_state_none
-    c_down_state_rect_initial = image_rects[0]
-    c_down_state_self = down_state_self
-    c_updates = updates
-    c_image_strip = image_strip
-    c_width, c_height = image_rects[0].size
-
-    # A key propagates its up/down state change to the adjacent white key on
-    # the left by calling the adjacent key's _right_black_down or
-    # _right_white_down method. 
-    #
-    if is_white_key:
-        key_color = 'white'
-    else:
-        key_color = 'black'
-    c_notify_down_method = "_right_%s_down" % key_color
-    c_notify_up_method = "_right_%s_up" % key_color
-
-    # Images:
-    #
-    # A black key only needs two images, for the up and down states. Its
-    # appearance is unaffected by the adjacent keys to its right, which cast no
-    # shadows upon it.
-    #
-    # A white key with a no adjacent black to its right only needs three
-    # images, for self up, self down, and both self and adjacent white down.
-    #
-    # A white key with both a black and white key to its right needs six
-    # images: self up, self up and adjacent black down, self down, self and
-    # adjacent white down, self and adjacent black down, and all three down.
-    #
-    # Each 'c_event' dictionary maps the current key state to a new key state,
-    # along with corresponding image, for the related event. If no redrawing
-    # is required for the state change then the image rect is simply None.
-    # 
-    c_event_down = {down_state_none: (down_state_self, image_rects[1])}
-    c_event_up = {down_state_self: (down_state_none, image_rects[0])}
-    c_event_right_white_down = {
-        down_state_none: (down_state_none, None),
-        down_state_self: (down_state_self, None)}
-    c_event_right_white_up = c_event_right_white_down.copy()
-    c_event_right_black_down = c_event_right_white_down.copy()
-    c_event_right_black_up = c_event_right_white_down.copy()
-    if len(image_rects) > 2:
-        c_event_down[down_state_white] = (
-            down_state_self_white, image_rects[2])
-        c_event_up[down_state_self_white] = (down_state_white, image_rects[0])
-        c_event_right_white_down[down_state_none] = (down_state_white, None)
-        c_event_right_white_down[down_state_self] = (
-            down_state_self_white, image_rects[2])
-        c_event_right_white_up[down_state_white] = (down_state_none, None)
-        c_event_right_white_up[down_state_self_white] = (
-            down_state_self, image_rects[1])
-        c_event_right_black_down[down_state_white] = (
-            down_state_white, None)
-        c_event_right_black_down[down_state_self_white] = (
-            down_state_self_white, None)
-        c_event_right_black_up[down_state_white] = (
-            down_state_white, None)
-        c_event_right_black_up[down_state_self_white] = (
-            down_state_self_white, None)
-    if len(image_rects) > 3:
-        c_event_down[down_state_black] = (
-            down_state_self_black, image_rects[4])
-        c_event_down[down_state_white_black] = (down_state_all, image_rects[5])
-        c_event_up[down_state_self_black] = (down_state_black, image_rects[3])
-        c_event_up[down_state_all] = (down_state_white_black, image_rects[3])
-        c_event_right_white_down[down_state_black] = (
-            down_state_white_black, None)
-        c_event_right_white_down[down_state_self_black] = (
-            down_state_all, image_rects[5])
-        c_event_right_white_up[down_state_white_black] = (
-            down_state_black, None)
-        c_event_right_white_up[down_state_all] = (
-            down_state_self_black, image_rects[4])
-        c_event_right_black_down[down_state_none] = (
-            down_state_black, image_rects[3])
-        c_event_right_black_down[down_state_self] = (
-            down_state_self_black, image_rects[4])
-        c_event_right_black_down[down_state_white] = (
-            down_state_white_black, image_rects[3])
-        c_event_right_black_down[down_state_self_white] = (
-            down_state_all, image_rects[5])
-        c_event_right_black_up[down_state_black] = (
-            down_state_none, image_rects[0])
-        c_event_right_black_up[down_state_self_black] = (
-            down_state_self, image_rects[1])
-        c_event_right_black_up[down_state_white_black] = (
-            down_state_white, image_rects[0])
-        c_event_right_black_up[down_state_all] = (
-            down_state_self_white, image_rects[2])
-
-
-    class Key(object):
-        """A key widget, maintains key state and draws the key's image
-
-        Constructor arguments:
-        ident - A unique key identifier. Any immutable type suitable as a key.
-        posn - The location of the key on the display surface.
-        key_left - Optional, the adjacent white key to the left. Changes in
-            up and down state are propagated to that key.
-
-        A key has an associated position and state. Related to state is the
-        image drawn. State changes are managed with method calls, one method
-        per event type. The up and down event methods are public. Other
-        internal methods are for passing on state changes to the key_left
-        key instance.
-
-        """
-
-        is_white = is_white_key
-
-        def __init__(self, ident, posn, key_left = None):
-            """Return a new Key instance
-
-            The initial state is up, with all adjacent keys to the right also
-            up.
-
-            """
-            if key_left is None:
-                key_left = null_key
-            rect = Rect(posn[0], posn[1], c_width, c_height)
-            self.rect = rect
-            self._state = c_down_state_initial
-            self._source_rect = c_down_state_rect_initial
-            self._ident = ident
-            self._hash = hash(ident)
-            self._notify_down = getattr(key_left, c_notify_down_method)
-            self._notify_up = getattr(key_left, c_notify_up_method)
-            self._key_left = key_left
-            self._background_rect = Rect(rect.left, rect.bottom - 10,
-                                         c_width, 10)
-            c_updates.add(self)
-
-        def down(self):
-            """Signal that this key has been depressed (is down)"""
-            
-            self._state, source_rect = c_event_down[self._state]
-            if source_rect is not None:
-                self._source_rect = source_rect
-                c_updates.add(self)
-                self._notify_down()
-
-        def up(self):
-            """Signal that this key has been released (is up)"""
-            
-            self._state, source_rect = c_event_up[self._state]
-            if source_rect is not None:
-                self._source_rect = source_rect
-                c_updates.add(self)
-                self._notify_up()
-
-        def _right_white_down(self):
-            """Signal that the adjacent white key has been depressed
-
-            This method is for internal propagation of events between
-            key instances.
-
-            """
-            
-            self._state, source_rect = c_event_right_white_down[self._state]
-            if source_rect is not None:
-                self._source_rect = source_rect
-                c_updates.add(self)
-
-        def _right_white_up(self):
-            """Signal that the adjacent white key has been released
-
-            This method is for internal propagation of events between
-            key instances.
-
-            """
-            
-            self._state, source_rect = c_event_right_white_up[self._state]
-            if source_rect is not None:
-                self._source_rect = source_rect
-                c_updates.add(self)
-
-        def _right_black_down(self):
-            """Signal that the adjacent black key has been depressed
-
-            This method is for internal propagation of events between
-            key instances.
-
-            """
-
-            self._state, source_rect = c_event_right_black_down[self._state]
-            if source_rect is not None:
-                self._source_rect = source_rect
-                c_updates.add(self)
-
-        def _right_black_up(self):
-            """Signal that the adjacent black key has been released
-
-            This method is for internal propagation of events between
-            key instances.
-
-            """
-
-            self._state, source_rect = c_event_right_black_up[self._state]
-            if source_rect is not None:
-                self._source_rect = source_rect
-                c_updates.add(self)
-
-        def __eq__(self, other):
-            """True if same identifiers"""
-            
-            return self._ident == other._ident
-
-        def __hash__(self):
-            """Return the immutable hash value"""
-            
-            return self._hash
-
-        def __str__(self):
-            """Return the key's identifier and position as a string"""
-            
-            return ("<Key %s at (%d, %d)>" %
-                    (self._ident, self.rect.top, self.rect.left))
-
-        def draw(self, surf, background, dirty_rects):
-            """Redraw the key on the surface surf
-
-            The background is redrawn. The altered region is added to the
-            dirty_rects list.
-
-            """
-            
-            surf.blit(background, self._background_rect, self._background_rect)
-            surf.blit(c_image_strip, self.rect, self._source_rect)
-            dirty_rects.append(self.rect)
-
-    return Key
-
-def key_images():
-    """Return a keyboard keys image strip and a mapping of image locations
-
-    The return tuple is a surface and a dictionary of rects mapped to key
-    type.
-
-    This function encapsulates the constants relevant to the keyboard image
-    file. There are five key types. One is the black key. The other four
-    white keys are determined by the proximity of the black keys. The plain
-    white key has no black key adjacent to it. A white-left and white-right
-    key has a black key to the left or right of it respectively. A white-center
-    key has a black key on both sides. A key may have up to six related
-    images depending on the state of adjacent keys to its right.
-
-    """
-
-    my_dir = os.path.split(os.path.abspath(__file__))[0]
-    strip_file = os.path.join(my_dir, 'data', 'midikeys.png')
-    white_key_width = 42
-    white_key_height = 160
-    black_key_width = 22
-    black_key_height = 94
-    strip = pygame.image.load(strip_file)
-    names = [
-        'black none', 'black self',
-        'white none', 'white self', 'white self-white',
-        'white-left none', 'white-left self', 'white-left black',
-        'white-left self-black', 'white-left self-white', 'white-left all',
-        'white-center none', 'white-center self',
-        'white-center black', 'white-center self-black',
-        'white-center self-white', 'white-center all',
-        'white-right none', 'white-right self', 'white-right self-white']
-    rects = {}
-    for i in range(2):
-        rects[names[i]] = Rect(i * white_key_width, 0,
-                               black_key_width, black_key_height)
-    for i in range(2, len(names)):
-        rects[names[i]] = Rect(i * white_key_width, 0,
-                               white_key_width, white_key_height)
-    return strip, rects
-
-class Keyboard(object):
-    """Musical keyboard widget
-
-    Constructor arguments:
-    start_note: midi note value of the starting note on the keyboard.
-    n_notes: number of notes (keys) on the keyboard.
-
-    A Keyboard instance draws the musical keyboard and maintains the state of
-    all the keyboard keys. Individual keys can be in a down (depressed) or
-    up (released) state.
-
-    """
-
-    _image_strip, _rects = key_images()
-
-    white_key_width, white_key_height = _rects['white none'].size
-    black_key_width, black_key_height = _rects['black none'].size
-
-    _updates = set()
-
-    # There are five key classes, representing key shape:
-    # black key (BlackKey), plain white key (WhiteKey), white key to the left
-    # of a black key (WhiteKeyLeft), white key between two black keys
-    # (WhiteKeyCenter), and white key to the right of a black key
-    # (WhiteKeyRight).
-    BlackKey = key_class(_updates,
-                         _image_strip,
-                         [_rects['black none'], _rects['black self']],
-                         False)
-    WhiteKey = key_class(_updates,
-                         _image_strip,
-                         [_rects['white none'],
-                          _rects['white self'],
-                          _rects['white self-white']])
-    WhiteKeyLeft = key_class(_updates,
-                             _image_strip,
-                             [_rects['white-left none'],
-                              _rects['white-left self'],
-                              _rects['white-left self-white'],
-                              _rects['white-left black'],
-                              _rects['white-left self-black'],
-                              _rects['white-left all']])
-    WhiteKeyCenter = key_class(_updates,
-                               _image_strip,
-                               [_rects['white-center none'],
-                                _rects['white-center self'],
-                                _rects['white-center self-white'],
-                                _rects['white-center black'],
-                                _rects['white-center self-black'],
-                                _rects['white-center all']])
-    WhiteKeyRight = key_class(_updates,
-                              _image_strip,
-                              [_rects['white-right none'],
-                               _rects['white-right self'],
-                               _rects['white-right self-white']])
-
-    def __init__(self, start_note, n_notes):
-        """Return a new Keyboard instance with n_note keys"""
-
-        self._start_note = start_note
-        self._end_note = start_note + n_notes - 1
-        self._add_keys()
-
-    def _add_keys(self):
-        """Populate the keyboard with key instances
-
-        Set the _keys and rect attributes.
-        
-        """
-
-        # Keys are entered in a list, where index is Midi note. Since there are
-        # only 128 possible Midi notes the list length is managable. Unassigned
-        # note positions should never be accessed, so are set None to ensure
-        # the bug is quickly detected.
-        #
-        key_map = [None] * 128
-
-        start_note = self._start_note
-        end_note = self._end_note
-        black_offset = self.black_key_width // 2
-        prev_white_key = None
-        x = y = 0
-        if is_white_key(start_note):
-            is_prev_white = True
-        else:
-            x += black_offset
-            is_prev_white = False
-        for note in range(start_note, end_note + 1):
-            ident = note  # For now notes uniquely identify keyboard keys.
-            if is_white_key(note):
-                if is_prev_white:
-                    if note == end_note or is_white_key(note + 1):
-                        key = self.WhiteKey(ident, (x, y), prev_white_key)
-                    else:
-                        key = self.WhiteKeyLeft(ident, (x, y), prev_white_key)
-                else:
-                    if note == end_note or is_white_key(note + 1):
-                        key = self.WhiteKeyRight(ident, (x, y), prev_white_key)
-                    else:
-                        key = self.WhiteKeyCenter(ident,
-                                                  (x, y),
-                                                  prev_white_key)
-                is_prev_white = True
-                x += self.white_key_width
-                prev_white_key = key
-            else:
-                key = self.BlackKey(ident,
-                                    (x - black_offset, y),
-                                    prev_white_key)
-                is_prev_white = False
-            key_map[note] = key
-        self._keys = key_map
-
-        kb_width = key_map[self._end_note].rect.right
-        kb_height = self.white_key_height
-        self.rect = Rect(0, 0, kb_width, kb_height)
-
-    def map_regions(self, regions):
-        """Draw the key regions onto surface regions.
-
-        Regions must have at least 3 byte pixels. Each pixel of the keyboard
-        rectangle is set to the color (note, velocity, 0). The regions surface
-        must be at least as large as (0, 0, self.rect.left, self.rect.bottom)
-
-        """
-
-        # First draw the white key regions. Then add the overlapping
-        # black key regions.
-        #
-        cutoff = self.black_key_height
-        black_keys = []
-        for note in range(self._start_note, self._end_note + 1):
-            key = self._keys[note]
-            if key.is_white:
-                fill_region(regions, note, key.rect, cutoff)
-            else:
-                black_keys.append((note, key))
-        for note, key in black_keys:
-            fill_region(regions, note, key.rect, cutoff)
-
-    def draw(self, surf, background, dirty_rects):
-        """Redraw all altered keyboard keys"""
-        
-        changed_keys = self._updates
-        while changed_keys:
-            changed_keys.pop().draw(surf, background, dirty_rects)
-
-    def key_down(self, note):
-        """Signal a key down event for note"""
-
-        self._keys[note].down()
-
-    def key_up(self, note):
-        """Signal a key up event for note"""
-
-        self._keys[note].up()
-
-def fill_region(regions, note, rect, cutoff):
-    """Fill the region defined by rect with a (note, velocity, 0) color
-
-    The velocity varies from a small value at the top of the region to
-    127 at the bottom. The vertical region 0 to cutoff is split into
-    three parts, with velocities 42, 84 and 127. Everything below cutoff
-    has velocity 127.
-
-    """
-
-    x, y, width, height = rect
-    if cutoff is None:
-        cutoff = height
-    delta_height = cutoff // 3
-    regions.fill((note, 42, 0),
-                 (x, y, width, delta_height))
-    regions.fill((note, 84, 0),
-                 (x, y + delta_height, width, delta_height))
-    regions.fill((note, 127, 0),
-                 (x, y + 2 * delta_height, width, height - 2 * delta_height))
-    
-def is_white_key(note):
-    """True if note is represented by a white key"""
-    
-    key_pattern = [True, False, True, True, False, True,
-                   False, True, True, False, True, False]
-    return key_pattern[(note - 21) % len(key_pattern)]
-
-
-def usage():
-    print "--input [device_id] : Midi message logger"
-    print "--output [device_id] : Midi piano keyboard"
-    print "--list : list available midi devices"
-
-def main(mode='output', device_id=None):
-    """Run a Midi example
-
-    Arguments:
-    mode - if 'output' run a midi keyboard output example
-              'input' run a midi event logger input example
-              'list' list available midi devices
-           (default 'output')
-    device_id - midi device number; if None then use the default midi input or
-                output device for the system
-
-    """
-
-    if mode == 'input':
-        input_main(device_id)
-    elif mode == 'output':
-        output_main(device_id)
-    elif mode == 'list':
-        print_device_info()
-    else:
-        raise ValueError("Unknown mode option '%s'" % mode)
-                
-if __name__ == '__main__':
-
-    try:
-        device_id = int( sys.argv[-1] )
-    except:
-        device_id = None
-
-    if "--input" in sys.argv or "-i" in sys.argv:
-
-        input_main(device_id)
-
-    elif "--output" in sys.argv or "-o" in sys.argv:
-        output_main(device_id)
-    elif "--list" in sys.argv or "-l" in sys.argv:
-        print_device_info()
-    else:
-        usage()
+"""Contains an example of midi input, and a separate example of midi output.
+
+By default it runs the output example.
+python midi.py --output
+python midi.py --input
+
+"""
+
+import sys
+import os
+
+import pygame
+import pygame.midi
+from pygame.locals import *
+
+try:  # Ensure set available for output example
+    set
+except NameError:
+    from sets import Set as set
+
+
+def print_device_info():
+    for i in range( pygame.midi.get_count() ):
+        r = pygame.midi.get_device_info(i)
+        (interf, name, input, output, opened) = r
+
+        in_out = ""
+        if input:
+            in_out = "(input)"
+        if output:
+            in_out = "(output)"
+
+        print ("%2i: interface :%s:, name :%s:, opened :%s:  %s" %
+               (i, interf, name, opened, in_out))
+        
+
+
+
+def input_main(device_id = None):
+    pygame.init()
+    pygame.fastevent.init()
+    event_get = pygame.fastevent.get
+    event_post = pygame.fastevent.post
+
+    pygame.midi.init()
+
+    print_device_info()
+
+
+    if device_id is None:
+        input_id = pygame.midi.get_default_input_device_id()
+    else:
+        input_id = device_id
+
+    print ("using input_id :%s:" % input_id)
+    i = pygame.midi.Input( input_id )
+
+    pygame.display.set_mode((1,1))
+
+
+
+    going = True
+    while going:
+        events = event_get()
+        for e in events:
+            if e.type in [QUIT]:
+                going = False
+            if e.type in [KEYDOWN]:
+                going = False
+            if e.type in [pygame.midi.MIDIIN]:
+                print (e)
+
+        if i.poll():
+            midi_events = i.read(10)
+            # convert them into pygame events.
+            midi_evs = pygame.midi.midis2events(midi_events, i.device_id)
+
+            for m_e in midi_evs:
+                event_post( m_e )
+
+    del i
+    pygame.midi.quit()
+
+
+
+def output_main(device_id = None):
+    """Execute a musical keyboard example for the Church Organ instrument
+
+    This is a piano keyboard example, with a two octave keyboard, starting at
+    note F3. Left mouse down over a key starts a note, left up stops it. The
+    notes are also mapped to the computer keyboard keys, assuming an American
+    English PC keyboard (sorry everyone else, but I don't know if I can map to
+    absolute key position instead of value.) The white keys are on the second
+    row, TAB to BACKSLASH, starting with note F3. The black keys map to the top
+    row, '1' to BACKSPACE, starting with F#3. 'r' is middle C. Close the
+    window or pressing ESCAPE to quit the program. Key velocity (note
+    amplitude) varies vertically on the keyboard image, with minimum velocity
+    at the top of a key and maximum velocity at bottom.
+
+    Midi output is to the default midi output device for the computer.
+    
+    """
+
+    # A note to new pygamers:
+    #
+    # All the midi module stuff is in this function. It is unnecessary to
+    # understand how the keyboard display works to appreciate how midi
+    # messages are sent.
+
+    # The keyboard is drawn by a Keyboard instance. This instance maps Midi
+    # notes to musical keyboard keys. A regions surface maps window position
+    # to (Midi note, velocity) pairs. A key_mapping dictionary does the same
+    # for computer keyboard keys. Midi sound is controlled with direct method
+    # calls to a pygame.midi.Output instance.
+    #
+    # Things to consider when using pygame.midi:
+    #
+    # 1) Initialize the midi module with a to pygame.midi.init().
+    # 2) Create a midi.Output instance for the desired output device port.
+    # 3) Select instruments with set_instrument() method calls.
+    # 4) Play notes with note_on() and note_off() method calls.
+    # 5) Call pygame.midi.Quit() when finished. Though the midi module tries
+    #    to ensure that midi is properly shut down, it is best to do it
+    #    explicitly. A try/finally statement is the safest way to do this.
+    #
+    GRAND_PIANO = 0
+    CHURCH_ORGAN = 19
+
+    instrument = CHURCH_ORGAN
+    #instrument = GRAND_PIANO
+    start_note = 53  # F3 (white key note), start_note != 0
+    n_notes = 24  # Two octaves (14 white keys)
+    
+    bg_color = Color('slategray')
+
+    key_mapping = make_key_mapping([K_TAB, K_1, K_q, K_2, K_w, K_3, K_e, K_r,
+                                    K_5, K_t, K_6, K_y, K_u, K_8, K_i, K_9,
+                                    K_o, K_0, K_p, K_LEFTBRACKET, K_EQUALS,
+                                    K_RIGHTBRACKET, K_BACKSPACE, K_BACKSLASH],
+                                   start_note)
+    
+
+
+    pygame.init()
+    pygame.midi.init()
+
+    print_device_info()
+
+    if device_id is None:
+        port = pygame.midi.get_default_output_device_id()
+    else:
+        port = device_id
+
+    print ("using output_id :%s:" % port)
+
+
+
+    midi_out = pygame.midi.Output(port, 0)
+    try:
+        midi_out.set_instrument(instrument)
+        keyboard = Keyboard(start_note, n_notes)
+
+        screen = pygame.display.set_mode(keyboard.rect.size)
+        screen.fill(bg_color)
+        pygame.display.flip()
+
+        background = pygame.Surface(screen.get_size())
+        background.fill(bg_color)
+        dirty_rects = []
+        keyboard.draw(screen, background, dirty_rects)
+        pygame.display.update(dirty_rects)
+
+        regions = pygame.Surface(screen.get_size())  # initial color (0,0,0)
+        keyboard.map_regions(regions)
+
+        pygame.event.set_blocked(MOUSEMOTION)
+        repeat = 1
+        mouse_note = 0
+        on_notes = set()
+        while 1:
+            update_rects = None
+            e = pygame.event.wait()
+            if e.type == pygame.MOUSEBUTTONDOWN:
+                mouse_note, velocity, __, __  = regions.get_at(e.pos)
+                if mouse_note and mouse_note not in on_notes:
+                    keyboard.key_down(mouse_note)
+                    midi_out.note_on(mouse_note, velocity)
+                    on_notes.add(mouse_note)
+                else:
+                    mouse_note = 0
+            elif e.type == pygame.MOUSEBUTTONUP:
+                if mouse_note:
+                    midi_out.note_off(mouse_note)
+                    keyboard.key_up(mouse_note)
+                    on_notes.remove(mouse_note)
+                    mouse_note = 0
+            elif e.type == pygame.QUIT:
+                break
+            elif e.type == pygame.KEYDOWN:
+                if e.key == pygame.K_ESCAPE:
+                    break
+                try:
+                    note, velocity = key_mapping[e.key]
+                except KeyError:
+                    pass
+                else:
+                    if note not in on_notes:
+                        keyboard.key_down(note)
+                        midi_out.note_on(note, velocity)
+                        on_notes.add(note)
+            elif e.type == pygame.KEYUP:
+                try:
+                    note, __ = key_mapping[e.key]
+                except KeyError:
+                    pass
+                else:
+                    if note in on_notes and note != mouse_note:
+                        keyboard.key_up(note)
+                        midi_out.note_off(note, 0)
+                        on_notes.remove(note)
+
+            dirty_rects = []
+            keyboard.draw(screen, background, dirty_rects)
+            pygame.display.update(dirty_rects)
+    finally:
+        del midi_out
+        pygame.midi.quit()
+
+def make_key_mapping(key_list, start_note):
+    """Return a dictionary of (note, velocity) by computer keyboard key code"""
+    
+    mapping = {}
+    for i in range(len(key_list)):
+        mapping[key_list[i]] = (start_note + i, 127)
+    return mapping
+
+class NullKey(object):
+    """A dummy key that ignores events passed to it by other keys
+
+    A NullKey instance is the left key instance used by default
+    for the left most keyboard key.
+
+    """
+    
+    def _right_white_down(self):
+        pass
+
+    def _right_white_up(self):
+        pass
+
+    def _right_black_down(self):
+        pass
+
+    def _right_black_up(self):
+        pass
+
+null_key = NullKey()
+
+def key_class(updates, image_strip, image_rects, is_white_key=True):
+    """Return a keyboard key widget class
+
+    Arguments:
+    updates - a set into which a key instance adds itself if it needs
+        redrawing.
+    image_strip - The surface containing the images of all key states.
+    image_rects - A list of Rects giving the regions within image_strip that
+        are relevant to this key class.
+    is_white_key (default True) - Set false if this is a black key.
+
+    This function automates the creation of a key widget class for the
+    three basic key types. A key has two basic states, up or down (
+    depressed). Corresponding up and down images are drawn for each
+    of these two states. But to give the illusion of depth, a key
+    may have shadows cast upon it by the adjacent keys to its right.
+    These shadows change depending on the up/down state of the key and
+    its neighbors. So a key may support multiple images and states
+    depending on the shadows. A key type is determined by the length
+    of image_rects and the value of is_white.
+
+    """
+
+    # Naming convention: Variables used by the Key class as part of a
+    # closure start with 'c_'.
+
+    # State logic and shadows:
+    #
+    # A key may cast a shadow upon the key to its left. A black key casts a
+    # shadow on an adjacent white key. The shadow changes depending of whether
+    # the black or white key is depressed. A white key casts a shadow on the
+    # white key to its left if it is up and the left key is down. Therefore
+    # a keys state, and image it will draw, is determined entirely by its
+    # itself and the key immediately adjacent to it on the right. A white key
+    # is always assumed to have an adjacent white key.
+    #
+    # There can be up to eight key states, representing all permutations
+    # of the three fundamental states of self up/down, adjacent white
+    # right up/down, adjacent black up/down.
+    # 
+    down_state_none = 0
+    down_state_self = 1
+    down_state_white = down_state_self << 1
+    down_state_self_white = down_state_self | down_state_white
+    down_state_black = down_state_white << 1
+    down_state_self_black = down_state_self | down_state_black
+    down_state_white_black = down_state_white | down_state_black
+    down_state_all = down_state_self | down_state_white_black
+
+    # Some values used in the class.
+    #
+    c_down_state_initial = down_state_none
+    c_down_state_rect_initial = image_rects[0]
+    c_down_state_self = down_state_self
+    c_updates = updates
+    c_image_strip = image_strip
+    c_width, c_height = image_rects[0].size
+
+    # A key propagates its up/down state change to the adjacent white key on
+    # the left by calling the adjacent key's _right_black_down or
+    # _right_white_down method. 
+    #
+    if is_white_key:
+        key_color = 'white'
+    else:
+        key_color = 'black'
+    c_notify_down_method = "_right_%s_down" % key_color
+    c_notify_up_method = "_right_%s_up" % key_color
+
+    # Images:
+    #
+    # A black key only needs two images, for the up and down states. Its
+    # appearance is unaffected by the adjacent keys to its right, which cast no
+    # shadows upon it.
+    #
+    # A white key with a no adjacent black to its right only needs three
+    # images, for self up, self down, and both self and adjacent white down.
+    #
+    # A white key with both a black and white key to its right needs six
+    # images: self up, self up and adjacent black down, self down, self and
+    # adjacent white down, self and adjacent black down, and all three down.
+    #
+    # Each 'c_event' dictionary maps the current key state to a new key state,
+    # along with corresponding image, for the related event. If no redrawing
+    # is required for the state change then the image rect is simply None.
+    # 
+    c_event_down = {down_state_none: (down_state_self, image_rects[1])}
+    c_event_up = {down_state_self: (down_state_none, image_rects[0])}
+    c_event_right_white_down = {
+        down_state_none: (down_state_none, None),
+        down_state_self: (down_state_self, None)}
+    c_event_right_white_up = c_event_right_white_down.copy()
+    c_event_right_black_down = c_event_right_white_down.copy()
+    c_event_right_black_up = c_event_right_white_down.copy()
+    if len(image_rects) > 2:
+        c_event_down[down_state_white] = (
+            down_state_self_white, image_rects[2])
+        c_event_up[down_state_self_white] = (down_state_white, image_rects[0])
+        c_event_right_white_down[down_state_none] = (down_state_white, None)
+        c_event_right_white_down[down_state_self] = (
+            down_state_self_white, image_rects[2])
+        c_event_right_white_up[down_state_white] = (down_state_none, None)
+        c_event_right_white_up[down_state_self_white] = (
+            down_state_self, image_rects[1])
+        c_event_right_black_down[down_state_white] = (
+            down_state_white, None)
+        c_event_right_black_down[down_state_self_white] = (
+            down_state_self_white, None)
+        c_event_right_black_up[down_state_white] = (
+            down_state_white, None)
+        c_event_right_black_up[down_state_self_white] = (
+            down_state_self_white, None)
+    if len(image_rects) > 3:
+        c_event_down[down_state_black] = (
+            down_state_self_black, image_rects[4])
+        c_event_down[down_state_white_black] = (down_state_all, image_rects[5])
+        c_event_up[down_state_self_black] = (down_state_black, image_rects[3])
+        c_event_up[down_state_all] = (down_state_white_black, image_rects[3])
+        c_event_right_white_down[down_state_black] = (
+            down_state_white_black, None)
+        c_event_right_white_down[down_state_self_black] = (
+            down_state_all, image_rects[5])
+        c_event_right_white_up[down_state_white_black] = (
+            down_state_black, None)
+        c_event_right_white_up[down_state_all] = (
+            down_state_self_black, image_rects[4])
+        c_event_right_black_down[down_state_none] = (
+            down_state_black, image_rects[3])
+        c_event_right_black_down[down_state_self] = (
+            down_state_self_black, image_rects[4])
+        c_event_right_black_down[down_state_white] = (
+            down_state_white_black, image_rects[3])
+        c_event_right_black_down[down_state_self_white] = (
+            down_state_all, image_rects[5])
+        c_event_right_black_up[down_state_black] = (
+            down_state_none, image_rects[0])
+        c_event_right_black_up[down_state_self_black] = (
+            down_state_self, image_rects[1])
+        c_event_right_black_up[down_state_white_black] = (
+            down_state_white, image_rects[0])
+        c_event_right_black_up[down_state_all] = (
+            down_state_self_white, image_rects[2])
+
+
+    class Key(object):
+        """A key widget, maintains key state and draws the key's image
+
+        Constructor arguments:
+        ident - A unique key identifier. Any immutable type suitable as a key.
+        posn - The location of the key on the display surface.
+        key_left - Optional, the adjacent white key to the left. Changes in
+            up and down state are propagated to that key.
+
+        A key has an associated position and state. Related to state is the
+        image drawn. State changes are managed with method calls, one method
+        per event type. The up and down event methods are public. Other
+        internal methods are for passing on state changes to the key_left
+        key instance.
+
+        """
+
+        is_white = is_white_key
+
+        def __init__(self, ident, posn, key_left = None):
+            """Return a new Key instance
+
+            The initial state is up, with all adjacent keys to the right also
+            up.
+
+            """
+            if key_left is None:
+                key_left = null_key
+            rect = Rect(posn[0], posn[1], c_width, c_height)
+            self.rect = rect
+            self._state = c_down_state_initial
+            self._source_rect = c_down_state_rect_initial
+            self._ident = ident
+            self._hash = hash(ident)
+            self._notify_down = getattr(key_left, c_notify_down_method)
+            self._notify_up = getattr(key_left, c_notify_up_method)
+            self._key_left = key_left
+            self._background_rect = Rect(rect.left, rect.bottom - 10,
+                                         c_width, 10)
+            c_updates.add(self)
+
+        def down(self):
+            """Signal that this key has been depressed (is down)"""
+            
+            self._state, source_rect = c_event_down[self._state]
+            if source_rect is not None:
+                self._source_rect = source_rect
+                c_updates.add(self)
+                self._notify_down()
+
+        def up(self):
+            """Signal that this key has been released (is up)"""
+            
+            self._state, source_rect = c_event_up[self._state]
+            if source_rect is not None:
+                self._source_rect = source_rect
+                c_updates.add(self)
+                self._notify_up()
+
+        def _right_white_down(self):
+            """Signal that the adjacent white key has been depressed
+
+            This method is for internal propagation of events between
+            key instances.
+
+            """
+            
+            self._state, source_rect = c_event_right_white_down[self._state]
+            if source_rect is not None:
+                self._source_rect = source_rect
+                c_updates.add(self)
+
+        def _right_white_up(self):
+            """Signal that the adjacent white key has been released
+
+            This method is for internal propagation of events between
+            key instances.
+
+            """
+            
+            self._state, source_rect = c_event_right_white_up[self._state]
+            if source_rect is not None:
+                self._source_rect = source_rect
+                c_updates.add(self)
+
+        def _right_black_down(self):
+            """Signal that the adjacent black key has been depressed
+
+            This method is for internal propagation of events between
+            key instances.
+
+            """
+
+            self._state, source_rect = c_event_right_black_down[self._state]
+            if source_rect is not None:
+                self._source_rect = source_rect
+                c_updates.add(self)
+
+        def _right_black_up(self):
+            """Signal that the adjacent black key has been released
+
+            This method is for internal propagation of events between
+            key instances.
+
+            """
+
+            self._state, source_rect = c_event_right_black_up[self._state]
+            if source_rect is not None:
+                self._source_rect = source_rect
+                c_updates.add(self)
+
+        def __eq__(self, other):
+            """True if same identifiers"""
+            
+            return self._ident == other._ident
+
+        def __hash__(self):
+            """Return the immutable hash value"""
+            
+            return self._hash
+
+        def __str__(self):
+            """Return the key's identifier and position as a string"""
+            
+            return ("<Key %s at (%d, %d)>" %
+                    (self._ident, self.rect.top, self.rect.left))
+
+        def draw(self, surf, background, dirty_rects):
+            """Redraw the key on the surface surf
+
+            The background is redrawn. The altered region is added to the
+            dirty_rects list.
+
+            """
+            
+            surf.blit(background, self._background_rect, self._background_rect)
+            surf.blit(c_image_strip, self.rect, self._source_rect)
+            dirty_rects.append(self.rect)
+
+    return Key
+
+def key_images():
+    """Return a keyboard keys image strip and a mapping of image locations
+
+    The return tuple is a surface and a dictionary of rects mapped to key
+    type.
+
+    This function encapsulates the constants relevant to the keyboard image
+    file. There are five key types. One is the black key. The other four
+    white keys are determined by the proximity of the black keys. The plain
+    white key has no black key adjacent to it. A white-left and white-right
+    key has a black key to the left or right of it respectively. A white-center
+    key has a black key on both sides. A key may have up to six related
+    images depending on the state of adjacent keys to its right.
+
+    """
+
+    my_dir = os.path.split(os.path.abspath(__file__))[0]
+    strip_file = os.path.join(my_dir, 'data', 'midikeys.png')
+    white_key_width = 42
+    white_key_height = 160
+    black_key_width = 22
+    black_key_height = 94
+    strip = pygame.image.load(strip_file)
+    names = [
+        'black none', 'black self',
+        'white none', 'white self', 'white self-white',
+        'white-left none', 'white-left self', 'white-left black',
+        'white-left self-black', 'white-left self-white', 'white-left all',
+        'white-center none', 'white-center self',
+        'white-center black', 'white-center self-black',
+        'white-center self-white', 'white-center all',
+        'white-right none', 'white-right self', 'white-right self-white']
+    rects = {}
+    for i in range(2):
+        rects[names[i]] = Rect(i * white_key_width, 0,
+                               black_key_width, black_key_height)
+    for i in range(2, len(names)):
+        rects[names[i]] = Rect(i * white_key_width, 0,
+                               white_key_width, white_key_height)
+    return strip, rects
+
+class Keyboard(object):
+    """Musical keyboard widget
+
+    Constructor arguments:
+    start_note: midi note value of the starting note on the keyboard.
+    n_notes: number of notes (keys) on the keyboard.
+
+    A Keyboard instance draws the musical keyboard and maintains the state of
+    all the keyboard keys. Individual keys can be in a down (depressed) or
+    up (released) state.
+
+    """
+
+    _image_strip, _rects = key_images()
+
+    white_key_width, white_key_height = _rects['white none'].size
+    black_key_width, black_key_height = _rects['black none'].size
+
+    _updates = set()
+
+    # There are five key classes, representing key shape:
+    # black key (BlackKey), plain white key (WhiteKey), white key to the left
+    # of a black key (WhiteKeyLeft), white key between two black keys
+    # (WhiteKeyCenter), and white key to the right of a black key
+    # (WhiteKeyRight).
+    BlackKey = key_class(_updates,
+                         _image_strip,
+                         [_rects['black none'], _rects['black self']],
+                         False)
+    WhiteKey = key_class(_updates,
+                         _image_strip,
+                         [_rects['white none'],
+                          _rects['white self'],
+                          _rects['white self-white']])
+    WhiteKeyLeft = key_class(_updates,
+                             _image_strip,
+                             [_rects['white-left none'],
+                              _rects['white-left self'],
+                              _rects['white-left self-white'],
+                              _rects['white-left black'],
+                              _rects['white-left self-black'],
+                              _rects['white-left all']])
+    WhiteKeyCenter = key_class(_updates,
+                               _image_strip,
+                               [_rects['white-center none'],
+                                _rects['white-center self'],
+                                _rects['white-center self-white'],
+                                _rects['white-center black'],
+                                _rects['white-center self-black'],
+                                _rects['white-center all']])
+    WhiteKeyRight = key_class(_updates,
+                              _image_strip,
+                              [_rects['white-right none'],
+                               _rects['white-right self'],
+                               _rects['white-right self-white']])
+
+    def __init__(self, start_note, n_notes):
+        """Return a new Keyboard instance with n_note keys"""
+
+        self._start_note = start_note
+        self._end_note = start_note + n_notes - 1
+        self._add_keys()
+
+    def _add_keys(self):
+        """Populate the keyboard with key instances
+
+        Set the _keys and rect attributes.
+        
+        """
+
+        # Keys are entered in a list, where index is Midi note. Since there are
+        # only 128 possible Midi notes the list length is managable. Unassigned
+        # note positions should never be accessed, so are set None to ensure
+        # the bug is quickly detected.
+        #
+        key_map = [None] * 128
+
+        start_note = self._start_note
+        end_note = self._end_note
+        black_offset = self.black_key_width // 2
+        prev_white_key = None
+        x = y = 0
+        if is_white_key(start_note):
+            is_prev_white = True
+        else:
+            x += black_offset
+            is_prev_white = False
+        for note in range(start_note, end_note + 1):
+            ident = note  # For now notes uniquely identify keyboard keys.
+            if is_white_key(note):
+                if is_prev_white:
+                    if note == end_note or is_white_key(note + 1):
+                        key = self.WhiteKey(ident, (x, y), prev_white_key)
+                    else:
+                        key = self.WhiteKeyLeft(ident, (x, y), prev_white_key)
+                else:
+                    if note == end_note or is_white_key(note + 1):
+                        key = self.WhiteKeyRight(ident, (x, y), prev_white_key)
+                    else:
+                        key = self.WhiteKeyCenter(ident,
+                                                  (x, y),
+                                                  prev_white_key)
+                is_prev_white = True
+                x += self.white_key_width
+                prev_white_key = key
+            else:
+                key = self.BlackKey(ident,
+                                    (x - black_offset, y),
+                                    prev_white_key)
+                is_prev_white = False
+            key_map[note] = key
+        self._keys = key_map
+
+        kb_width = key_map[self._end_note].rect.right
+        kb_height = self.white_key_height
+        self.rect = Rect(0, 0, kb_width, kb_height)
+
+    def map_regions(self, regions):
+        """Draw the key regions onto surface regions.
+
+        Regions must have at least 3 byte pixels. Each pixel of the keyboard
+        rectangle is set to the color (note, velocity, 0). The regions surface
+        must be at least as large as (0, 0, self.rect.left, self.rect.bottom)
+
+        """
+
+        # First draw the white key regions. Then add the overlapping
+        # black key regions.
+        #
+        cutoff = self.black_key_height
+        black_keys = []
+        for note in range(self._start_note, self._end_note + 1):
+            key = self._keys[note]
+            if key.is_white:
+                fill_region(regions, note, key.rect, cutoff)
+            else:
+                black_keys.append((note, key))
+        for note, key in black_keys:
+            fill_region(regions, note, key.rect, cutoff)
+
+    def draw(self, surf, background, dirty_rects):
+        """Redraw all altered keyboard keys"""
+        
+        changed_keys = self._updates
+        while changed_keys:
+            changed_keys.pop().draw(surf, background, dirty_rects)
+
+    def key_down(self, note):
+        """Signal a key down event for note"""
+
+        self._keys[note].down()
+
+    def key_up(self, note):
+        """Signal a key up event for note"""
+
+        self._keys[note].up()
+
+def fill_region(regions, note, rect, cutoff):
+    """Fill the region defined by rect with a (note, velocity, 0) color
+
+    The velocity varies from a small value at the top of the region to
+    127 at the bottom. The vertical region 0 to cutoff is split into
+    three parts, with velocities 42, 84 and 127. Everything below cutoff
+    has velocity 127.
+
+    """
+
+    x, y, width, height = rect
+    if cutoff is None:
+        cutoff = height
+    delta_height = cutoff // 3
+    regions.fill((note, 42, 0),
+                 (x, y, width, delta_height))
+    regions.fill((note, 84, 0),
+                 (x, y + delta_height, width, delta_height))
+    regions.fill((note, 127, 0),
+                 (x, y + 2 * delta_height, width, height - 2 * delta_height))
+    
+def is_white_key(note):
+    """True if note is represented by a white key"""
+    
+    key_pattern = [True, False, True, True, False, True,
+                   False, True, True, False, True, False]
+    return key_pattern[(note - 21) % len(key_pattern)]
+
+
+def usage():
+    print ("--input [device_id] : Midi message logger")
+    print ("--output [device_id] : Midi piano keyboard")
+    print ("--list : list available midi devices")
+
+def main(mode='output', device_id=None):
+    """Run a Midi example
+
+    Arguments:
+    mode - if 'output' run a midi keyboard output example
+              'input' run a midi event logger input example
+              'list' list available midi devices
+           (default 'output')
+    device_id - midi device number; if None then use the default midi input or
+                output device for the system
+
+    """
+
+    if mode == 'input':
+        input_main(device_id)
+    elif mode == 'output':
+        output_main(device_id)
+    elif mode == 'list':
+        print_device_info()
+    else:
+        raise ValueError("Unknown mode option '%s'" % mode)
+                
+if __name__ == '__main__':
+
+    try:
+        device_id = int( sys.argv[-1] )
+    except:
+        device_id = None
+
+    if "--input" in sys.argv or "-i" in sys.argv:
+
+        input_main(device_id)
+
+    elif "--output" in sys.argv or "-o" in sys.argv:
+        output_main(device_id)
+    elif "--list" in sys.argv or "-l" in sys.argv:
+        print_device_info()
+    else:
+        usage()

examples/scrap_clipboard.py

 import StringIO
 
 def usage ():
-    print "Press the 'g' key to get all of the current clipboard data"
-    print "Press the 'p' key to put a string into the clipboard"
-    print "Press the 'a' key to get a list of the currently available types"
-    print "Press the 'i' key to put an image into the clipboard"
+    print ("Press the 'g' key to get all of the current clipboard data")
+    print ("Press the 'p' key to put a string into the clipboard")
+    print ("Press the 'a' key to get a list of the currently available types")
+    print ("Press the 'i' key to put an image into the clipboard")
 
 main_dir = os.path.split(os.path.abspath(__file__))[0]
 
 
         elif e.type == KEYDOWN and e.key == K_g:
             # This means to look for data.
-            print "Getting the different clipboard data.."
+            print ("Getting the different clipboard data..")
             for t in scrap.get_types ():
                 r = scrap.get (t)
                 if r and len (r) > 500:
-                    print "Type %s : (large buffer)" % t
+                    print ("Type %s : (large buffer)" % t)
                 else:
-                    print "Type %s : %s" % (t, r)
+                    print ("Type %s : %s" % (t, r))
                 if "image" in t:
                     namehint = t.split("/")[1]
                     if namehint in ['bmp', 'png', 'jpg']:
 
         elif e.type == KEYDOWN and e.key == K_p:
             # Place some text into the selection.
-            print "Placing clipboard text."
+            print ("Placing clipboard text.")
             scrap.put (SCRAP_TEXT, "Hello. This is a message from scrap.")
 
         elif e.type == KEYDOWN and e.key == K_a:
             # Get all available types.
-            print "Getting the available types from the clipboard."
+            print ("Getting the available types from the clipboard.")
             types = scrap.get_types ()
-            print types
+            print (types)
             if len (types) > 0:
-                print "Contains %s: %s" % (types[0], scrap.contains (types[0]))
-                print "Contains _INVALID_: ", scrap.contains ("_INVALID_")
+                print ("Contains %s: %s" % (types[0], scrap.contains (types[0])))
+                print ("Contains _INVALID_: ", scrap.contains ("_INVALID_"))
 
         elif e.type == KEYDOWN and e.key == K_i:
-            print "Putting image into the clipboard."
+            print ("Putting image into the clipboard.")
             scrap.set_mode (SCRAP_CLIPBOARD)
             fp = open (os.path.join(main_dir, 'data', 'liquid.bmp'), 'rb')
             buf = fp.read ()

examples/sound_array_demos.py

 
     a1 = sndarray.array(sound)
     if mydebug:
-        print 'SHAPE1:', a1.shape
+        print ('SHAPE1: %s' % (a1.shape,))
 
     length = a1.shape[0]
 
         #size = (a1.shape[0] + int(a1.shape[0] + (echo_length * 3000)),)
 
     if mydebug:
-        print int(echo_length * a1.shape[0])
+        print (int(echo_length * a1.shape[0]))
     myarr = zeros(size, int32)
 
 
 
     if mydebug:
-        print "size", size
-        print myarr.shape
+        print ("size %s" % (size,))
+        print (myarr.shape)
     myarr[:length] = a1
-    #print myarr[3000:length+3000]
-    #print a1 >> 1
-    #print "a1.shape", a1.shape
+    #print (myarr[3000:length+3000])
+    #print (a1 >> 1)
+    #print ("a1.shape %s" % (a1.shape,))
     #c = myarr[3000:length+(3000*mult)]
-    #print "c.shape", c.shape
+    #print ("c.shape %s" % (c.shape,))
 
     incr = int(samples_per_second / echo_length)
     gap = length
     myarr[incr*4:gap+(incr*4)] += a1>>4
 
     if mydebug:
-        print 'SHAPE2:', myarr.shape
+        print ('SHAPE2: %s' % (myarr.shape,))
 
 
     sound2 = sndarray.make_sound(myarr.astype(int16))
            rate - at which the sound should be slowed down.  eg. 0.5 would be half speed.
     """
 
-    raise NotImplementedError
+    raise NotImplementedError()
     grow_rate = 1 / rate
 
     # make it 1/rate times longer.
     a1 = sndarray.array(sound)
 
     surf = pygame.surfarray.make_surface(a1)
-    print a1.shape[0] * grow_rate
+    print (a1.shape[0] * grow_rate)
     scaled_surf = pygame.transform.scale(surf, (int(a1.shape[0] * grow_rate), a1.shape[1]))
-    print scaled_surf
-    print surf
+    print (scaled_surf)
+    print (surf)
 
     a2 = a1 * rate
-    print a1.shape
-    print a2.shape
-    print a2
+    print (a1.shape)
+    print (a2.shape)
+    print (a2)
     sound2 = sndarray.make_sound(a2.astype(int16))
     return sound2
 
         elif 'numeric' in sndarray.get_arraytype():
             sndfarray.use_arraytype('numeric')
         else:
-            raise ImportError, 'No array package is installed'
+            raise ImportError('No array package is installed')
     else:
         sndarray.use_arraytype(arraytype)
     pygame.surfarray.use_arraytype(sndarray.get_arraytype())
     else:
         from Numeric import zeros, Int16 as int16, Int32 as int32
 
-    print "Using %s array package" % sndarray.get_arraytype()
-    print "mixer.get_init", mixer.get_init()
+    print ("Using %s array package" % sndarray.get_arraytype())
+    print ("mixer.get_init %s" % (mixer.get_init(),))
     inited = mixer.get_init()
 
     samples_per_second = pygame.mixer.get_init()[0]
 
     
 
-    print ("-" * 30) + "\n"
-    print "loading sound"
+    print (("-" * 30) + "\n")
+    print ("loading sound")
     sound = mixer.Sound(os.path.join(main_dir, 'data', 'car_door.wav'))
 
 
 
-    print "-" * 30
-    print "start positions"
-    print "-" * 30
+    print ("-" * 30)
+    print ("start positions")
+    print ("-" * 30)
 
     start_pos = 0.1
     sound2 = sound_from_pos(sound, start_pos, samples_per_second)
 
-    print "sound.get_length", sound.get_length()
-    print "sound2.get_length", sound2.get_length()
+    print ("sound.get_length %s" % (sound.get_length(),))
+    print ("sound2.get_length %s" % (sound2.get_length(),))
     sound2.play()
     while mixer.get_busy():
         pygame.time.wait(200)
 
-    print "waiting 2 seconds"
+    print ("waiting 2 seconds")
     pygame.time.wait(2000)
-    print "playing original sound"
+    print ("playing original sound")
 
     sound.play()
     while mixer.get_busy():
         pygame.time.wait(200)
 
-    print "waiting 2 seconds"
+    print ("waiting 2 seconds")
     pygame.time.wait(2000)
 
 
 
     if 0:
         #TODO: this is broken.
-        print ("-" * 30) + "\n"
-        print "Slow down the original sound."
+        print (("-" * 30) + "\n")
+        print ("Slow down the original sound.")
         rate = 0.2
         slowed_sound = slow_down_sound(sound, rate)
 
             pygame.time.wait(200)
 
 
-    print "-" * 30
-    print "echoing"
-    print "-" * 30
+    print ("-" * 30)
+    print ("echoing")
+    print ("-" * 30)
 
     t1 = time.time()
     sound2 = make_echo(sound, samples_per_second)
-    print "time to make echo", time.time() - t1
+    print ("time to make echo %i" % (time.time() - t1,))
 
 
-    print "original sound"
+    print ("original sound")
     sound.play()
     while mixer.get_busy():
         pygame.time.wait(200)
 
-    print "echoed sound"
+    print ("echoed sound")
     sound2.play()
     while mixer.get_busy():
         pygame.time.wait(200)
 
     t1 = time.time()
     sound3 = make_echo(sound, samples_per_second)
-    print "time to make echo", time.time() - t1
+    print ("time to make echo %i" % (time.time() - t1,))
 
-    print "original sound"
+    print ("original sound")
     sound.play()
     while mixer.get_busy():
         pygame.time.wait(200)
 
 
-    print "echoed sound"
+    print ("echoed sound")
     sound3.play()
     while mixer.get_busy():
         pygame.time.wait(200)
 
 
 def usage():
-    print "Usage: command line option [--numpy|--numeric]"
-    print "  The default is to use NumPy if installed,"
-    print "  otherwise Numeric"
+    print ("Usage: command line option [--numpy|--numeric]")
+    print ("  The default is to use NumPy if installed,")
+    print ("  otherwise Numeric")
 
 if __name__ == '__main__':
     if len(sys.argv) == 2:

examples/vgrade.py

     from Numeric import *
     from RandomArray import *
 except ImportError:
-    raise SystemExit, 'This example requires Numeric and the pygame surfarray module'
+    raise SystemExit('This example requires Numeric and the pygame surfarray module')
 
+pygame.surfarray.use_arraytype('numeric')
 
 timer = 0
 def stopwatch(message = None):
         return
     now = pygame.time.get_ticks()
     runtime = (now - timer)/1000.0 + .001
-    print message, runtime, ('seconds\t(%.2ffps)'%(1.0/runtime))
+    print ("%s %s %s" %
+           (message, runtime, ('seconds\t(%.2ffps)'%(1.0/runtime))))
     timer = now
 
 
 
 
 class MissingModule:
+    _NOT_IMPLEMENTED_ = True
     def __init__(self, name, info='', urgent=0):
         self.name = name
         self.info = str(info)

lib/threads/__init__.py

 from pygame.compat import geterror
 
 if sys.version_info[0] == 3:
-    from multiprocessing import Queue
+    from multiprocessing import JoinableQueue as Queue
     from queue import Empty
 elif (sys.version_info[0] == 2 and sys.version_info[1] < 5):
     from Py25Queue import Queue
         
         return map(lambda x:x.result, results)
     else:
-        return [wq, results]
+        return [wq, results]
 
 """
 
-# Any tests in IGNORE will not be run
-IGNORE = set ([
-    "scrap_test",
-])
-
-# Subprocess has less of a need to worry about interference between tests
-SUBPROCESS_IGNORE = set ([
-    "scrap_test",
-])
-
 if __name__ == 'pygame.tests':
     from pygame.tests.test_utils.run_tests import run
 else:

test/cdrom_tags.py

+__tags__ = ['interactive']

test/cdrom_test.py

-#################################### IMPORTS ###################################
-
-__tags__ = ['interactive']
-
-if __name__ == '__main__':
-    import sys
-    import os
-    pkg_dir = os.path.split(os.path.abspath(__file__))[0]
-    parent_dir, pkg_name = os.path.split(pkg_dir)
-    is_pygame_pkg = (pkg_name == 'tests' and
-                     os.path.split(parent_dir)[1] == 'pygame')
-    if not is_pygame_pkg:
-        sys.path.insert(0, parent_dir)
-else:
-    is_pygame_pkg = __name__.startswith('pygame.tests.')
-
-if is_pygame_pkg:
-    from pygame.tests.test_utils \
-         import test_not_implemented, question, prompt, unittest
-else:
-    from test.test_utils \
-         import test_not_implemented, question, prompt, unittest
-
-import pygame
-
-################################################################################
-
-class CdromModuleTest(unittest.TestCase):
-    def todo_test_CD(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.CD:
-
-          # pygame.cdrom.CD(id): return CD
-          # class to manage a cdrom drive
-          # 
-          # You can create a CD object for each cdrom on the system. Use
-          # pygame.cdrom.get_count() to determine how many drives actually
-          # exist. The id argument is an integer of the drive, starting at zero.
-          # 
-          # The CD object is not initialized, you can only call CD.get_id() and
-          # CD.get_name() on an uninitialized drive.
-          # 
-          # It is safe to create multiple CD objects for the same drive, they
-          # will all cooperate normally.
-          # 
-
-        self.fail() 
-
-    def todo_test_get_count(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.get_count:
-
-          # pygame.cdrom.get_count(): return count
-          # number of cd drives on the system
-          # 
-          # Return the number of cd drives on the system. When you create CD
-          # objects you need to pass an integer id that must be lower than this
-          # count. The count will be 0 if there are no drives on the system.
-          # 
-
-        self.fail() 
-
-    def todo_test_get_init(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.get_init:
-
-          # pygame.cdrom.get_init(): return bool
-          # true if the cdrom module is initialized
-          # 
-          # Test if the cdrom module is initialized or not. This is different
-          # than the CD.init() since each drive must also be initialized
-          # individually.
-          # 
-
-        self.fail() 
-
-    def todo_test_init(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.init:
-
-          # pygame.cdrom.init(): return None
-          # initialize the cdrom module
-          # 
-          # Initialize the cdrom module. This will scan the system for all CD
-          # devices. The module must be initialized before any other functions
-          # will work. This automatically happens when you call pygame.init().
-          # 
-          # It is safe to call this function more than once. 
-
-        self.fail() 
-
-    def todo_test_quit(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.quit:
-
-          # pygame.cdrom.quit(): return None
-          # uninitialize the cdrom module
-          # 
-          # Uninitialize the cdrom module. After you call this any existing CD
-          # objects will no longer work.
-          # 
-          # It is safe to call this function more than once. 
-
-        self.fail() 
-
-class CDTypeTest(unittest.TestCase):
-    def setUp(self):
-        pygame.cdrom.init()
-
-        #TODO:
-        try:
-            self.cd = pygame.cdrom.CD(0)
-        except pygame.error:
-            self.cd = None
-
-    def tearDown(self):
-        pygame.cdrom.quit()
-
-    def test_1_eject(self):
-
-        # __doc__ (as of 2008-07-02) for pygame.cdrom.CD.eject:
-
-          # CD.eject(): return None
-          # eject or open the cdrom drive
-        
-        # should raise if cd object not initialized
-        if self.cd:
-            self.cd.init()
-            self.cd.eject()
-
-            self.assert_(question('Did the cd eject?'))
-    
-            prompt("Please close the cd drive")
-
-    def test_2_get_name(self):
-
-        # __doc__ (as of 2008-07-02) for pygame.cdrom.CD.get_name:
-
-          # CD.get_name(): return name
-          # the system name of the cdrom drive
-
-        if self.cd:
-            cd_name = self.cd.get_name()
-    
-            self.assert_ (
-                question('Is %s the correct name for the cd drive?' % cd_name)
-            )
-
-    def todo_test_get_all(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.CD.get_all:
-
-          # CD.get_all(): return [(audio, start, end, lenth), ...]
-          # get all track information
-          # 
-          # Return a list with information for every track on the cdrom. The
-          # information consists of a tuple with four values. The audio value is
-          # True if the track contains audio data. The start, end, and length
-          # values are floating point numbers in seconds. Start and end
-          # represent absolute times on the entire disc.
-          # 
-
-        self.fail() 
-
-    def todo_test_get_busy(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.CD.get_busy:
-
-          # CD.get_busy(): return bool
-          # true if the drive is playing audio
-          # 
-          # Returns True if the drive busy playing back audio. 
-
-        self.fail() 
-
-    def todo_test_get_current(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.CD.get_current:
-
-          # CD.get_current(): return track, seconds
-          # the current audio playback position
-          # 
-          # Returns both the current track and time of that track. This method
-          # works when the drive is either playing or paused.
-          # 
-          # Note, track 0 is the first track on the CD.  Track numbers start at zero. 
-
-        self.fail() 
-
-    def todo_test_get_empty(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.CD.get_empty:
-
-          # CD.get_empty(): return bool
-          # False if a cdrom is in the drive
-          # 
-          # Return False if there is a cdrom currently in the drive. If the
-          # drive is empty this will return True.
-          # 
-
-        self.fail() 
-
-    def todo_test_get_id(self):
-
-        # __doc__ (as of 2008-08-02) for pygame.cdrom.CD.get_id:
-
<