Anonymous avatar Anonymous committed 195b49e

Merged to trunk revision 2256

Comments (0)

Files changed (25)

 examines some of the simple effects from the Pygame example,
 arraydemo.py.</dd>
 
+<dt><a href="tut/camera/CameraIntro.html">Camera Module Introduction</a>
+</dt><dd>Pygame, as of 1.9, has a camera module that allows you to capture
+images, watch live streams, and do some basic computer vision. This tutorial
+covers those use cases.</dd>
+
 <dt><a href="tut/newbieguide.html">Newbie Guide</a></dt><dd> A list of
 thirteen helpful tips for people to get comfortable using Pygame.</dd>
 

docs/ref/camera.html

   <tr><td><a href="camera.html#pygame.camera.Camera">pygame.camera.Camera</a> - <font size=-1>load a camera</font></td><td>load a camera</td></tr>
 </table></small></ul>
 <p>Pygame currently supports only Linux and v4l2 cameras. </p>
-<p><tt>EXPERIMENTAL!:</tt> meaning this api may change, or dissapear in later pygame releases. If you use this, your code will break with the next pygame release. </p>
+<p><tt>EXPERIMENTAL!:</tt> This api may change or disappear in later pygame releases. If you use this, your code will very likely break with the next pygame release. </p>
 <p>The Bayer to <tt>RGB</tt> function is based on: </p>
 <pre> Sonix SN9C101 based webcam basic I/F routines
  Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp>
   <tr><td><a href="camera.html#Camera.get_image">Camera.get_image</a> - <font size=-1>captures an image as a Surface</font></td><td>captures an image as a Surface</td></tr>
   <tr><td><a href="camera.html#Camera.get_raw">Camera.get_raw</a> - <font size=-1>returns an unmodified image as a string</font></td><td>returns an unmodified image as a string</td></tr>
 </table></small></ul>
-<p>Loads a v4l2 camera. The device is typically something like "/dev/video0". Default width and height are 640 by 480. Format is the desired colorspace of the output. This is useful for computer vision purposes. The following are supported: </p>
+<p>Loads a v4l2 camera. The device is typically something like "/dev/video0". Default width and height are 640 by 480. Format is the desired colorspace of the output. This is useful for computer vision purposes. The default is <tt>RGB</tt>. The following are supported: </p>
 <ul>
  <li> RGB - Red, Green, Blue </li>
  <li> YUV - Luma, Blue Chrominance, Red Chrominance </li>
 <big><b>Camera.start</big></b><br><ul>
   <i>opens, initializes, and starts capturing</i><br>
   <tt>Camera.start(): return None</tt><br>
-<p>Opens the camera device, attempts to initialize it, and begins recording images to a buffer. </p>
+<p>Opens the camera device, attempts to initialize it, and begins recording images to a buffer. The camera must be started before any of the below functions can be used. </p>
 <!--COMMENTS:Camera.start--> &nbsp;<br> 
 <br></ul>
 
 <big><b>Camera.stop</big></b><br><ul>
   <i>stops, uninitializes, and closes the camera</i><br>
   <tt>Camera.stop(): return None</tt><br>
-<p>Stops recording, uninitializes the camera, and closes it. </p>
+<p>Stops recording, uninitializes the camera, and closes it. Once a camera is stopped, the below functions cannot be used until it is started again. </p>
 <!--COMMENTS:Camera.stop--> &nbsp;<br> 
 <br></ul>
 
 <a name="Camera.get_controls">
 <big><b>Camera.get_controls</big></b><br><ul>
   <i>gets current values of user controls</i><br>
-  <tt>Camera.get_controls(): return (hflip = bool, vflip = bool)</tt><br>
-<p>If the camera supports it, get_controls will return the current settings for horizontal and vertical image flip as bools. If unsupported, it will return the default values of (0, 0). Note that the return values here may be different than those returned by set_controls, though these are more likely to be correct. </p>
+  <tt>Camera.get_controls(): return (hflip = bool, vflip = bool, brightness)</tt><br>
+<p>If the camera supports it, get_controls will return the current settings for horizontal and vertical image flip as bools and brightness as an int. If unsupported, it will return the default values of (0, 0, 0). Note that the return values here may be different than those returned by set_controls, though these are more likely to be correct. </p>
 <!--COMMENTS:Camera.get_controls--> &nbsp;<br> 
 <br></ul>
 
 <a name="Camera.set_controls">
 <big><b>Camera.set_controls</big></b><br><ul>
   <i>changes camera settings if supported by the camera</i><br>
-  <tt>Camera.set_controls(hflip = bool, vflip = bool): return (hflip = bool, vflip = bool)</tt><br>
+  <tt>Camera.set_controls(hflip = bool, vflip = bool, brightness): return (hflip = bool, vflip = bool, brightness)</tt><br>
 <p>Allows you to change camera settings if the camera supports it. The return values will be the input values if the camera claims it succeeded or the values previously in use if not. Each argument is optional, and the desired one can be chosen by supplying the keyword, like hflip. Note that the actual settings being used by the camera may not be the same as those returned by set_controls. </p>
 <!--COMMENTS:Camera.set_controls--> &nbsp;<br> 
 <br></ul>
 <big><b>Camera.get_size</big></b><br><ul>
   <i>returns the dimensions of the images being recorded</i><br>
   <tt>Camera.get_size(): return (width, height)</tt><br>
-<p>Returns the current dimensions of the images being captured by the camera. </p>
+<p>Returns the current dimensions of the images being captured by the camera. This will return the actual size, which may be different than the one specified during initialization if the camera did not support that size. </p>
 <!--COMMENTS:Camera.get_size--> &nbsp;<br> 
 <br></ul>
 
 <big><b>Camera.query_image</big></b><br><ul>
   <i>checks if a frame is ready</i><br>
   <tt>Camera.query_image(): return bool</tt><br>
-<p>If an image is ready to get, it returns true. Otherwise it returns false. Note that some webcams will always return False and will only queue a frame when called with a blocking function like get_image(). </p>
+<p>If an image is ready to get, it returns true. Otherwise it returns false. Note that some webcams will always return False and will only queue a frame when called with a blocking function like get_image(). This is useful to separate the framerate of the game from that of the camera without having to use threading. </p>
 <!--COMMENTS:Camera.query_image--> &nbsp;<br> 
 <br></ul>
 

docs/ref/transform.html

 <a name="pygame.transform.average_surfaces">
 <big><b>pygame.transform.average_surfaces</big></b><br><ul>
   <i>find the average surface from many surfaces.</i><br>
-  <tt>pygame.transform.average_surfaces(Surfaces, DestSurface = None): return Surface</tt><br>
+  <tt>pygame.transform.average_surfaces(Surfaces, DestSurface = None, palette_colors = 1): return Surface</tt><br>
 <p>Takes a sequence of surfaces and returns a surface with average colors from each of the surfaces. </p>
-<p>New in pygame <tt>1.8</tt> </p>
+<p>palette_colors - if true we average the colors in palette, otherwise we average the pixel values. This is useful if the surface is actually greyscale colors, and not palette colors. </p>
+<p>Note, this function currently does not handle palette using surfaces correctly. </p>
+<p>New in pygame <tt>1.8</tt> palette_colors argument new in pygame <tt>1.9</tt> </p>
 <!--COMMENTS:pygame.transform.average_surfaces--> &nbsp;<br> 
 <br></ul>
 

docs/tut/camera/CameraIntro.html

+<html><head><!--
+TUTORIAL:Camera Module Introduction
+-->
+  <title>Pygame Tutorials - Camera Module Introduction</title>
+</head>
+<body>
+     
+<h1 align="center"><font size="-1">Pygame Tutorials</font><br>
+ Camera Module Introduction</h1>
+   
+<h2 align="center">by Nirav Patel<br>
+ <font size="-1">nrp@eclecti.cc</font></h2>
+   
+<h3 align="center">Revision 1.0, May 25th, 2009</h3>
+<br><br>
+
+Pygame 1.9 comes with support for interfacing cameras, allowing you to capture
+still images, watch live streams, and do some simple computer vision.  This
+tutorial will cover all of those use cases, providing code samples you can base
+your app or game on.  You can refer to the <a href="../../ref/camera.html">
+reference documentation</a> for the full API.
+<br><br>
+
+<i>Note:  As of Pygame 1.9, the camera module offers native support for cameras
+that use v4l2 on Linux.  There is support for other platforms via Videocapture
+or OpenCV, but this guide will focus on the native module.  Most of the code
+will be valid for other platforms, but certain things like controls will not
+work.  The module is also marked as <b>EXPERIMENTAL</b>, meaning the API could
+change in subsequent versions.</i>
+<br><br>
+
+<h3>Import and Init</h3>
+<pre>
+    import pygame
+    import pygame.camera
+    from pygame.locals import *
+
+    pygame.init()
+    pygame.camera.init()
+</pre>
+As the camera module is optional, it needs to be imported and initialized
+manually as shown above.
+<br><br>
+
+<h3>Capturing a Single Image</h3>
+Now we will go over the simplest case of opening a camera and capturing a frame
+as a surface.  In the below example, we assume that there is a camera at
+/dev/video0 on the computer, and initialize it with a size of 640 by 480.
+The surface called image is whatever the camera was seeing when get_image() was
+called.
+<pre>
+    cam = pygame.camera.Camera("/dev/video0",(640,480))
+    cam.start()
+    image = cam.get_image()
+</pre>
+<h4>Listing Connected Cameras</h4>
+You may be wondering, what if we don't know the exact path of the camera?
+We can ask the module to provide a list of cameras attached to the
+computer and initialize the first camera in the list.
+<pre>
+    camlist = pygame.camera.list_cameras()
+    if camlist:
+        cam = pygame.caemra.Camera(camlist[0],(640,480))
+</pre>
+<h4>Using Camera Controls</h4>
+Most cameras support controls like flipping the image and changing brightness.
+set_controls() and get_controls() can be used at any point after using start().
+<pre>
+    cam.set_controls(hflip = True, vflip = False)
+    print camera.get_controls()
+</pre>
+<br>
+<h3>Capturing a Live Stream</h3>
+The rest of this tutorial will be based around capturing a live stream of
+images.  For this, we will be using the class below.  As described, it will
+simply blit a constant stream of camera frames to the screen, effectively
+showing live video.  It is basically what you would expect, looping get_image(),
+blitting to the display surface, and flipping it.  For performance reasons,
+we will be supplying the camera with the same surface to use each time.
+<pre>
+class Capture(object):
+    def __init__(self):
+        self.size = (640,480)
+        # create a display surface. standard pygame stuff
+        self.display = pygame.display.set_mode(self.size, 0)
+        
+        # this is the same as what we saw before
+        self.clist = pygame.camera.list_cameras()
+        if not self.clist:
+            raise ValueError("Sorry, no cameras detected.")
+        self.cam = pygame.camera.Camera(self.clist[0], self.size)
+        self.cam.start()
+
+        # create a surface to capture to.  for performance purposes
+        # bit depth is the same as that of the display surface.
+        self.snapshot = pygame.surface.Surface(self.size, 0, self.display)
+
+    def get_and_flip(self):
+        # if you don't want to tie the framerate to the camera, you can check 
+        # if the camera has an image ready.  note that while this works
+        # on most cameras, some will never return true.
+        if self.cam.query_image():
+            self.snapshot = self.cam.get_image(self.snapshot)
+
+        # blit it to the display surface.  simple!
+        self.display.blit(self.snapshot, (0,0))
+        pygame.display.flip()
+
+    def main(self):
+        going = True
+        while going:
+            events = pygame.event.get()
+            for e in events:
+                if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
+                    # close the camera safely
+                    self.cam.stop()
+                    going = False
+
+            self.get_and_flip()
+</pre>
+Since get_image() is a blocking call that could take quite a bit of time on a
+slow camera, this example uses query_image() to see if the camera is ready.
+This allows you to separate the framerate of your game from that of your camera.
+It is also possible to have the camera capturing images in a separate thread,
+for approximately the same performance gain, if you find that your camera does
+not support the query_image() function correctly.
+<br><br>
+
+<h3>Basic Computer Vision</h3>
+By using the camera, transform, and mask modules, pygame can do some basic
+computer vision.
+<br>
+
+<h4>Colorspaces</h4>
+When initializing a camera, colorspace is an optional parameter, with 'RGB',
+'YUV', and 'HSV' as the possible choices.  YUV and HSV are both generally more
+useful for computer vision than RGB, and allow you to more easily threshold by
+color, something we will look at later in the tutorial.
+<pre>
+    self.cam = pygame.camera.Camera(self.clist[0], self.size, "RGB")
+    <img src="rgb.jpg">
+    self.cam = pygame.camera.Camera(self.clist[0], self.size, "YUV")
+    <img src="yuv.jpg">
+    self.cam = pygame.camera.Camera(self.clist[0], self.size, "HSV")
+    <img src="hsv.jpg">
+</pre>
+
+<h4>Thresholding</h4>
+Using the threshold() function from the transform module, one can do simple
+green screen like effects, or isolate specifically colored objects in a scene.
+In the below example, we threshold out just the green tree and make the rest
+of the image black.  Check the reference documentation for details on the
+<a href="../../ref/transform.html#pygame.transform.threshold">threshold
+function</a>.
+<pre>
+    self.thresholded = pygame.surface.Surface(self.size, 0, self.display)
+    self.snapshot = self.cam.get_image(self.snapshot)
+    pygame.transform.threshold(self.thresholded,self.snapshot,(0,255,0),(90,170,170),(0,0,0),2)
+    <img src="thresholded.jpg">
+</pre>
+Of course, this is only useful if you already know the exact color of the object
+you are looking for.  To get around this and make thresholding usable in the
+real world, we need to add a calibration stage where we identify the color of an
+object and use it to threshold against.  We will be using the average_color()
+function of the transform module to do this.  Below is an example calibration
+function that you could loop until an event like a key press, and an image of
+what it would look like.  The color inside the box will be the one that is
+used for the threshold.  Note that we are using the HSV colorspace in the below
+images.
+<pre>
+    def calibrate(self):
+        # capture the image
+        self.snapshot = self.cam.get_image(self.snapshot)
+        # blit it to the display surface
+        self.display.blit(self.snapshot, (0,0))
+        # make a rect in the middle of the screen
+        crect = pygame.draw.rect(self.display, (255,0,0), (145,105,30,30), 4)
+        # get the average color of the area inside the rect
+        self.ccolor = pygame.transform.average_color(self.snapshot, crect)
+        # fill the upper left corner with that color
+        self.display.fill(self.ccolor, (0,0,50,50))
+        pygame.display.flip()
+    <img src="average.jpg">
+    pygame.transform.threshold(self.thresholded,self.snapshot,self.ccolor,(30,30,30),(0,0,0),2)
+    <img src="thresh.jpg">
+</pre>
+You can use the same idea to do a simple green screen/blue screen, by first
+getting a background image and then thresholding against it.  The below example
+just has the camera pointed at a blank white wall in HSV colorspace.
+<pre>
+    def calibrate(self):
+        # capture a bunch of background images
+        bg = []
+        for i in range(0,5):
+          bg.append(self.cam.get_image(self.background))
+        # average them down to one to get rid of some noise
+        pygame.transform.average_surfaces(bg,self.background)
+        # blit it to the display surface
+        self.display.blit(self.background, (0,0))
+        pygame.display.flip()
+    <img src="background.jpg">
+    pygame.transform.threshold(self.thresholded,self.snapshot,(0,255,0),(30,30,30),(0,0,0),1,self.background)
+    <img src="green.jpg">
+</pre>
+    
+<h4>Using the Mask Module</h4>
+The stuff above is great if you just want to display images, but with the 
+<a href="../../ref/mask.html">mask module</a>, you can also use a camera as an
+input device for a game.  For example, going back to the example of
+thresholding out a specific object, we can find the position of that object and
+use it to control an on screen object.
+<pre>
+    def get_and_flip(self):
+        self.snapshot = self.cam.get_image(self.snapshot)
+        # threshold against the color we got before
+        mask = pygame.mask.from_threshold(self.snapshot, self.ccolor, (30, 30, 30))
+        self.display.blit(self.snapshot,(0,0))
+        # keep only the largest blob of that color
+        connected = mask.connected_component()
+        # make sure the blob is big enough that it isn't just noise
+        if mask.count() > 100:
+            # find the center of the blob
+            coord = mask.centroid()
+            # draw a circle with size variable on the size of the blob
+            pygame.draw.circle(self.display, (0,255,0), coord, max(min(50,mask.count()/400),5))
+        pygame.display.flip()
+    <img src="mask.jpg">
+</pre>
+This is just the most basic example.  You can track multiple different colored
+blobs, find the outlines of objects, have collision detection between real life
+and in game objects, get the angle of an object to allow for even finer control,
+and more.  Have fun!
+</body></html>
Add a comment to this file

docs/tut/camera/average.jpg

Added
New image
Add a comment to this file

docs/tut/camera/background.jpg

Added
New image
Add a comment to this file

docs/tut/camera/green.jpg

Added
New image
Add a comment to this file

docs/tut/camera/hsv.jpg

Added
New image
Add a comment to this file

docs/tut/camera/mask.jpg

Added
New image
Add a comment to this file

docs/tut/camera/rgb.jpg

Added
New image
Add a comment to this file

docs/tut/camera/thresh.jpg

Added
New image
Add a comment to this file

docs/tut/camera/thresholded.jpg

Added
New image
Add a comment to this file

docs/tut/camera/yuv.jpg

Added
New image
 
     # here are the .py/.pyo/.pyc files we need to ask to remove.
     py_to_remove = ["color"]
-
+    
+    if os.name == "e32": # Don't warn on Symbian. The color.py is used as a wrapper.
+        py_to_remove = []
 
     # See if any of the files are there.
     extension_files = ["%s%s" % (x, extension_ext) for x in ext_to_remove]
 portmidi supports (currently windows, OSX, and linux).
 
 This uses pyportmidi for now, but may use its own bindings at some
-point soon.
+point in the future.
 
 New in pygame 1.9.0.
 """
 
 
 #TODO:
-#    - export docs from .py to .doc.
-#    - generate test stubs (probably after docs are written)
-#        - $ cd test/util/
-#          $ python gen_stubs.py sprite.Sprite
-#    - start writing tests.
+#    - finish writing tests.
+#        - likely as interactive tests... so you'd need to plug in a midi device.
 #    - create a background thread version for input threads.
 #        - that can automatically inject input into the event queue
 #          once the input object is running.  Like joysticks.
 MIDIOUT = pygame.locals.USEREVENT + 11
 
 _init = False
-pypm = None
+_pypm = None
+
+
+__all__ = [ "Input",
+            "MIDIIN",
+            "MIDIOUT",
+            "MidiException",
+            "Output",
+            "get_count",
+            "get_default_input_id",
+            "get_default_output_id",
+            "get_device_info",
+            "init",
+            "midis2events",
+            "quit",
+            "time",
+           ]
+
+__theclasses__ = ["Input", "Output"]
 
 
 def init():
     
     It is safe to call this more than once.
     """
-    global _init, pypm
+    global _init, _pypm
     if not _init:
         import pygame.pypm
-        pypm = pygame.pypm
+        _pypm = pygame.pypm
 
-        pypm.Initialize()
+        _pypm.Initialize()
         _init = True
         atexit.register(quit)
 
 
     It is safe to call this function more than once.
     """
-    global _init, pypm
+    global _init, _pypm
     if _init:
         # TODO: find all Input and Output classes and close them first?
-        pypm.Terminate()
+        _pypm.Terminate()
         _init = False
-        del pypm
-        #del pygame.pypm
+        del _pypm
+        #del pygame._pypm
 
 def _check_init():
     if not _init:
     Device ids range from 0 to get_count() -1
     """
     _check_init()
-    return pypm.CountDevices()
+    return _pypm.CountDevices()
 
 
 
 
-def get_default_input_device_id():
-    """gets the device number of the default input device.
-    pygame.midi.get_default_input_device_id(): return default_id
-
-
+def get_default_input_id():
+    """gets default input device number
+    pygame.midi.get_default_input_id(): return default_id
+    
+    
     Return the default device ID or -1 if there are no devices.
     The result can be passed to the Input()/Ouput() class.
-
+    
     On the PC, the user can specify a default device by
     setting an environment variable. For example, to use device #1.
-
+    
         set PM_RECOMMENDED_INPUT_DEVICE=1
-
+    
     The user should first determine the available device ID by using
     the supplied application "testin" or "testout".
-
+    
     In general, the registry is a better place for this kind of info,
     and with USB devices that can come and go, using integers is not
     very reliable for device identification. Under Windows, if
     in the registry is "USB", and device 1 is named
     "In USB MidiSport 1x1", then that will be the default
     input because it contains the string "USB".
-
+    
     In addition to the name, get_device_info() returns "interf", which
     is the interface name. (The "interface" is the underlying software
-	system or API used by PortMidi to access devices. Examples are
-	MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.)
-	At present, the only Win32 interface is "MMSystem", the only Linux
-	interface is "ALSA", and the only Max OS X interface is "CoreMIDI".
+    system or API used by PortMidi to access devices. Examples are
+    MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.)
+    At present, the only Win32 interface is "MMSystem", the only Linux
+    interface is "ALSA", and the only Max OS X interface is "CoreMIDI".
     To specify both the interface and the device name in the registry,
     separate the two with a comma and a space, e.g.:
         MMSystem, In USB MidiSport 1x1
     In this case, the string before the comma must be a substring of
     the "interf" string, and the string after the space must be a
     substring of the "name" name string in order to match the device.
+    
+    Note: in the current release, the default is simply the first device
+    (the input or output device with the lowest PmDeviceID).
+    """
+    return _pypm.GetDefaultInputDeviceID()
 
-    Note: in the current release, the default is simply the first device
-	(the input or output device with the lowest PmDeviceID).
-    """
-    return pypm.GetDefaultInputDeviceID()
 
 
 
-
-def get_default_output_device_id():
-    """get the device number of the default output device.
-    pygame.midi.get_default_output_device_id(): return default_id
-
-
+def get_default_output_id():
+    """gets default output device number
+    pygame.midi.get_default_output_id(): return default_id
+    
+    
     Return the default device ID or -1 if there are no devices.
     The result can be passed to the Input()/Ouput() class.
-
+    
     On the PC, the user can specify a default device by
     setting an environment variable. For example, to use device #1.
-
+    
         set PM_RECOMMENDED_OUTPUT_DEVICE=1
-
+    
     The user should first determine the available device ID by using
     the supplied application "testin" or "testout".
-
+    
     In general, the registry is a better place for this kind of info,
     and with USB devices that can come and go, using integers is not
     very reliable for device identification. Under Windows, if
     in the registry is "USB", and device 1 is named
     "In USB MidiSport 1x1", then that will be the default
     input because it contains the string "USB".
-
+    
     In addition to the name, get_device_info() returns "interf", which
     is the interface name. (The "interface" is the underlying software
-	system or API used by PortMidi to access devices. Examples are
-	MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.)
-	At present, the only Win32 interface is "MMSystem", the only Linux
-	interface is "ALSA", and the only Max OS X interface is "CoreMIDI".
+    system or API used by PortMidi to access devices. Examples are
+    MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.)
+    At present, the only Win32 interface is "MMSystem", the only Linux
+    interface is "ALSA", and the only Max OS X interface is "CoreMIDI".
     To specify both the interface and the device name in the registry,
     separate the two with a comma and a space, e.g.:
         MMSystem, In USB MidiSport 1x1
     In this case, the string before the comma must be a substring of
     the "interf" string, and the string after the space must be a
     substring of the "name" name string in order to match the device.
-
+    
     Note: in the current release, the default is simply the first device
-	(the input or output device with the lowest PmDeviceID).
+    (the input or output device with the lowest PmDeviceID).
     """
-    return pypm.GetDefaultOutputDeviceID()
+    return _pypm.GetDefaultOutputDeviceID()
 
 
 def get_device_info(an_id):
-    """ returns (interf, name, input, output, opened)
+    """ returns information about a midi device
     pygame.midi.get_device_info(an_id): return (interf, name, input, output, opened) 
 
+    interf - a text string describing the device interface, eg 'ALSA'.
+    name - a text string for the name of the device, eg 'Midi Through Port-0'
+    input - 0, or 1 if the device is an input device.
+    output - 0, or 1 if the device is an output device.
+    opened - 0, or 1 if the device is opened.
+
     If the id is out of range, the function returns None.
     """
-    return pypm.GetDeviceInfo(an_id) 
-
-
-class MidiException(Exception):
-    def __init__(self, value):
-        self.parameter = value
-    def __str__(self):
-        return repr(self.parameter)
+    return _pypm.GetDeviceInfo(an_id) 
 
 
 class Input(object):
         The buffer_size specifies the number of input events to be buffered 
         waiting to be read using Input.read().
         """
-        self._input = pypm.Input(device_id, buffer_size)
+        self._input = _pypm.Input(device_id, buffer_size)
         self.device_id = device_id
 
 
         raises a MidiException on error.
         """
         r = self._input.Poll()
-        if r == pypm.TRUE:
+        if r == _pypm.TRUE:
             return True
-        elif r == pypm.FALSE:
+        elif r == _pypm.FALSE:
             return False
         else:
             err_text = GetErrorText(r)
 
 
 class Output(object):
+    """Output is used to send midi to an output device
+    Output(device_id)
+    Output(device_id, latency = 0)
+    Output(device_id, buffer_size = 4096)
+    Output(device_id, latency, buffer_size)
+
+    The buffer_size specifies the number of output events to be 
+    buffered waiting for output.  (In some cases -- see below -- 
+    PortMidi does not buffer output at all and merely passes data 
+    to a lower-level API, in which case buffersize is ignored.)
+
+    latency is the delay in milliseconds applied to timestamps to determine
+    when the output should actually occur. (If latency is < 0, 0 is 
+    assumed.)
+
+    If latency is zero, timestamps are ignored and all output is delivered
+    immediately. If latency is greater than zero, output is delayed until
+    the message timestamp plus the latency. (NOTE: time is measured 
+    relative to the time source indicated by time_proc. Timestamps are 
+    absolute, not relative delays or offsets.) In some cases, PortMidi 
+    can obtain better timing than your application by passing timestamps 
+    along to the device driver or hardware. Latency may also help you 
+    to synchronize midi data to audio data by matching midi latency to 
+    the audio buffer latency.
+
+    """
+
     def __init__(self, device_id, latency = 0, buffer_size = 4096):
-        """
-        Output(device_id)
+        """Output(device_id)
         Output(device_id, latency = 0)
         Output(device_id, buffer_size = 4096)
         Output(device_id, latency, buffer_size)
         to synchronize midi data to audio data by matching midi latency to 
         the audio buffer latency.
         """
-        self._output = pypm.Output(device_id, latency)
+        self._output = _pypm.Output(device_id, latency)
         self.device_id = device_id
 
     def write(self, data):
-        """writes a list of midi data to the Output.
+        """writes a list of midi data to the Output
         Output.write(data)
 
         writes series of MIDI information in the form of a list:
 
 
     def write_short(self, status, data1 = 0, data2 = 0):
-        """ write_short(status <, data1><, data2>)
+        """write_short(status <, data1><, data2>)
         Output.write_short(status)
         Output.write_short(status, data1 = 0, data2 = 0)
 
         """writes a timestamped system-exclusive midi message.
         Output.write_sys_ex(when, msg)
 
-        write_sys_ex(<timestamp>,<msg>)
-
         msg - can be a *list* or a *string*
+        when - a timestamp in miliseconds
         example:
           (assuming o is an onput MIDI stream)
             o.write_sys_ex(0,'\\xF0\\x7D\\x10\\x11\\x12\\x13\\xF7')
           is equivalent to
-            o.write_sys_ex(pygame.midi.Time,
+            o.write_sys_ex(pygame.midi.time(),
                            [0xF0,0x7D,0x10,0x11,0x12,0x13,0xF7])
         """
         self._output.WriteSysEx(when, msg)
 
 
     def note_on(self, note, velocity=None, channel = 0):
-        """ turns a midi note on.  Note must be off.
+        """turns a midi note on.  Note must be off.
         Output.note_on(note, velocity=None, channel = 0)
 
         Turn a note on in the output stream.  The note must already
         self.write_short(0x90+channel, note, velocity)
 
     def note_off(self, note, velocity=None, channel = 0):
-        """ turns a midi note off.  Note must be on.
+        """turns a midi note off.  Note must be on.
         Output.note_off(note, velocity=None, channel = 0)
 
         Turn a note off in the output stream.  The note must already
 
 
     def set_instrument(self, instrument_id, channel = 0):
-        """ Select an instrument, with a value between 0 and 127.
+        """select an instrument, with a value between 0 and 127
         Output.set_instrument(instrument_id, channel = 0)
 
         """
 def time():
     """returns the current time in ms of the PortMidi timer
     pygame.midi.time(): return time
+
+    The time is reset to 0, when the module is inited.
     """
-    return pypm.Time()
+    return _pypm.Time()
 
 
 
 
 
 
+class MidiException(Exception):
+    """exception that pygame.midi functions and classes can raise
+    MidiException(errno)
+    """
+    def __init__(self, value):
+        self.parameter = value
+    def __str__(self):
+        return repr(self.parameter)
 
+
+

msys_build_deps.py

 pmlib = libportmidi.a
 pmimplib = libportmidi.dll.a
 pmcomsrc = $(pmcom)/portmidi.c $(pmcom)/pmutil.c
-pmwinsrc = $(pmwin)/pmwin.c $(pmwin)/pmwinmm.c
-pmobj = portmidi.o pmutil.o pmwin.o pmwinmm.o
+pmwinsrc = $(pmwin)/pmwin.c $(pmwin)/pmwinmm_.c
+pmobj = portmidi.o pmutil.o pmwin.o pmwinmm_.o
 pmsrc = $(pmcomsrc) $(pmwinsrc)
 pmreqhdr = $(pmcom)/portmidi.h $(pmcom)/pmutil.h
 pmhdr = $(pmreqhdr) $(pmcom)/pminternal.h $(pmwin)/pmwinmm.h
 all : $(pmdll)
 .PHONY : all
 
+$(pmwin)/pmwinmm_.c : $(pmwin)/pmwinmm.c
+\tsed 's_#define DEBUG.*$$_/*&*/_' < "$<" > "$@"
+
 $(pmlib) : $(src) $(hdr)
 \t$(CC) $(CPPFLAGS) $(IHDR) -c $(CFLAGS) $(src)
 \tar rc $(pmlib) $(obj)
 .PHONY : clean
 
 clean :
-\trm -f $(obj) $(pmdll) $(pmimplib) $(pmlib)
+\trm -f $(obj) $(pmdll) $(pmimplib) $(pmlib) $(pmwin)/pmwinmm_.c
 THE_END
 
   cat > portmidi.def << 'THE_END'
   make clean
   rm -f GNUmakefile portmidi.def
 fi
+
+exit 0
 """),
     ]  # End dependencies = [.
 
 
 Pygame currently supports only Linux and v4l2 cameras.
 
-EXPERIMENTAL!: meaning this api may change, or dissapear in later 
-pygame releases.  If you use this, your code will break with the 
-next pygame release.
+EXPERIMENTAL!: This api may change or disappear in later 
+pygame releases.  If you use this, your code will very likely
+break with the next pygame release.
 
 
 
 
 Loads a v4l2 camera.  The device is typically something like "/dev/video0".
 Default width and height are 640 by 480.  Format is the desired colorspace of
-the output.  This is useful for computer vision purposes.  The following are
-supported:
+the output.  This is useful for computer vision purposes.  The default
+is RGB.  The following are supported:
 
 * RGB - Red, Green, Blue
 * YUV - Luma, Blue Chrominance, Red Chrominance
 Camera.start(): return None
 
 Opens the camera device, attempts to initialize it, and begins recording
-images to a buffer.
+images to a buffer.  The camera must be started before any of the below
+functions can be used.
 <END>
 
 
 stops, uninitializes, and closes the camera
 Camera.stop(): return None
 
-Stops recording, uninitializes the camera, and closes it.
+Stops recording, uninitializes the camera, and closes it.  Once a camera
+is stopped, the below functions cannot be used until it is started again.
 <END>
 
 
 get_controls
 gets current values of user controls
-Camera.get_controls(): return (hflip = bool, vflip = bool)
+Camera.get_controls(): return (hflip = bool, vflip = bool, brightness)
 
 If the camera supports it, get_controls will return the current settings for
-horizontal and vertical image flip as bools.  If unsupported, it will return
-the default values of (0, 0).  Note that the return values here may be different
-than those returned by set_controls, though these are more likely to be correct.
+horizontal and vertical image flip as bools and brightness as an int.  If
+unsupported, it will return the default values of (0, 0, 0).
+Note that the return values here may be different than those returned by
+set_controls, though these are more likely to be correct.
 <END>
 
 set_controls
 changes camera settings if supported by the camera
-Camera.set_controls(hflip = bool, vflip = bool): return (hflip = bool, vflip = bool)
+Camera.set_controls(hflip = bool, vflip = bool, brightness): return (hflip = bool, vflip = bool, brightness)
 
 Allows you to change camera settings if the camera supports it.  The return
 values will be the input values if the camera claims it succeeded or the values
 Camera.get_size(): return (width, height)
 
 Returns the current dimensions of the images being captured by the camera.
+This will return the actual size, which may be different than the one
+specified during initialization if the camera did not support that size.
 <END>
 
 query_image
 
 If an image is ready to get, it returns true.  Otherwise it returns false.  Note
 that some webcams will always return False and will only queue a frame when
-called with a blocking function like get_image().
+called with a blocking function like get_image().  This is useful to
+separate the framerate of the game from that of the camera without having to
+use threading.
 <END>
 
 
 
 #define DOC_CAMERASTOP "Camera.stop(): return None\nstops, uninitializes, and closes the camera"
 
-#define DOC_CAMERAGETCONTROLS "Camera.get_controls(): return (hflip = bool, vflip = bool)\ngets current values of user controls"
-
-#define DOC_CAMERASETCONTROLS "Camera.set_controls(hflip = bool, vflip = bool): return (hflip = bool, vflip = bool)\nchanges camera settings if supported by the camera"
+#define DOC_CAMERAGETCONTROLS "Camera.get_controls(): return (hflip = bool, vflip = bool, brightness)\ngets current values of user controls"
+
+#define DOC_CAMERASETCONTROLS "Camera.set_controls(hflip = bool, vflip = bool, brightness): return (hflip = bool, vflip = bool, brightness)\nchanges camera settings if supported by the camera"
 
 #define DOC_CAMERAGETSIZE "Camera.get_size(): return (width, height)\nreturns the dimensions of the images being recorded"
 
 
 #define DOC_PYGAMETRANSFORMLAPLACIAN "pygame.transform.laplacian(Surface, DestSurface = None): return Surface\nfind edges in a surface"
 
-#define DOC_PYGAMETRANSFORMAVERAGESURFACES "pygame.transform.average_surfaces(Surfaces, DestSurface = None): return Surface\nfind the average surface from many surfaces."
+#define DOC_PYGAMETRANSFORMAVERAGESURFACES "pygame.transform.average_surfaces(Surfaces, DestSurface = None, palette_colors = 1): return Surface\nfind the average surface from many surfaces."
 
 #define DOC_PYGAMETRANSFORMAVERAGECOLOR "pygame.transform.average_color(Surface, Rect = None): return Color\nfinds the average color of a surface"
 
 
 
 Camera.get_controls
- Camera.get_controls(): return (hflip = bool, vflip = bool)
+ Camera.get_controls(): return (hflip = bool, vflip = bool, brightness)
 gets current values of user controls
 
 
 
 Camera.set_controls
- Camera.set_controls(hflip = bool, vflip = bool): return (hflip = bool, vflip = bool)
+ Camera.set_controls(hflip = bool, vflip = bool, brightness): return (hflip = bool, vflip = bool, brightness)
 changes camera settings if supported by the camera
 
 
 
 
 pygame.transform.average_surfaces
- pygame.transform.average_surfaces(Surfaces, DestSurface = None): return Surface
+ pygame.transform.average_surfaces(Surfaces, DestSurface = None, palette_colors = 1): return Surface
 find the average surface from many surfaces.
 
 

symbian/SConscript.app.py

                 icons = [ ("../lib/pygame_icon.svg", "pygame") ],
                 package=PACKAGE_NAME,
                 capabilities = CAPABILITIES,
-                epocheapsize = ( 0x5000, 0x200000 ),
+                # 100k, 4MB
+                epocheapsize = ( 0x19000, 0x400000 ),
                 epocstacksize = 0x14000,
                 winscw_options = "-w noempty",
 )
     #kwargs["target"] = abspath( kwargs["target"] )
     ToPackage( package = PACKAGE_NAME, **kwargs )
 
-def packagePyS60Stdlib(**kwargs):
-    kwargs["source"] = join( "deps/PythonForS60/module-repo/standard-modules", kwargs["source"] )
-    doPackage( **kwargs )
 
+doPackage( source = "app/pygame_main.py", target = "data/pygame", 
+           dopycompile=False )
+doPackage( source = "app/launcher/pygame_launcher.py", target = "data/pygame/launcher", 
+           dopycompile=False )
+doPackage( source = "app/apps/liquid_s60.py", target = "data/pygame/apps", 
+           dopycompile=False )
+doPackage( source = "app/launcher/logo.jpg", target = "data/pygame/launcher" )
 
-doPackage( source = "app/pygame_main.py", target = "data/pygame", dopycompile=False )
-doPackage( source = "app/launcher/pygame_launcher.py", target = "data/pygame/launcher" )
 
-doPackage( source = "app/launcher/logo.jpg", target = "data/pygame/launcher" )
-doPackage( source = "app/apps/liquid_s60.py", target = "data/pygame/apps" )
-packagePyS60Stdlib( source = "glob.py",    target = "data/pygame/libs" )
-packagePyS60Stdlib( source = "fnmatch.py", target = "data/pygame/libs" )
-
-

symbian/SConscript.pygame.py

 # Install pygame python libraries
 from glob import glob
 
+pylibzip = "data/pygame/libs/pygame.zip"
 def to_package(**kwargs):
     kwargs["source"] = abspath( kwargs["source"] )
-    ToPackage( package = PACKAGE_NAME, **kwargs )
+    return ToPackage( package = PACKAGE_NAME, pylibzip = pylibzip, 
+               dopycompile = ".pyc", **kwargs )
 
 pygame_lib = join( PATH_PY_LIBS, "pygame" )
 
 # Copy main pygame libs
+IGNORED_FILES = ["camera.py"]
 for x in glob( "../lib/*.py"):
-    to_package( source = x, target = pygame_lib )
+    for i in IGNORED_FILES:
+        if x.endswith( i ): break 
+    else:
+        to_package( source = x, target = pygame_lib )
 
 for x in glob( "../lib/threads/*.py"):
     to_package( source = x, target = join( pygame_lib, "threads") )
     to_package( source = x, target = pygame_lib )
     
 # Install default font
-to_package( source = "../lib/freesansbold.ttf", target = pygame_lib )
+#to_package( source = "../lib/freesansbold.ttf", target = pygame_lib )
+
+
+
+def packagePyS60Stdlib(**kwargs):
+    kwargs["source"] = join( "deps/PythonForS60/module-repo/standard-modules", kwargs["source"] )
+    return to_package( **kwargs )
+
+packagePyS60Stdlib( source = "glob.py",    target = "data/pygame/libs" )
+zippath = packagePyS60Stdlib( source = "fnmatch.py", target = "data/pygame/libs" )
+
+File2Zip( zippath, "../lib/freesansbold.ttf", "pygame/freesansbold.ttf" )

symbian/app/launcher/pygame_launcher.py

         return c * math.sin(t / d * (math.pi / 2)) + b
     
     def tweenEaseInOutSine(self, t, b, c, d, s=1.70158):
-        return - c / 2 * (math.cos(math.pi * t / d) - 1) + b;
+        return ( - c / 2 * (math.cos(math.pi * t / d) - 1) ) / 2 + b;
     
     def tweenEaseInBack(self, t, b, c, d, s=1.7158):
         t /= d
           
         B = - r.width
         X = B * v 
-        
+        #print B, X, v
         if direction == 1: 
             surf.blit(surfnew, (B - X, 0))
             surf.blit(surfold, (-X, 0))
         a1 = 255 * v
         a2 = 255 - a1 
         
-        #print "blend blit 1", time.time(),"->"
         surfnew.set_alpha(a1)
         surf.blit(surfnew, (0, 0))
-        #surf.fill((a1, a1, a1), None, BLEND_RGB_MULT)
-        #print time.time()
         
-        #print "blend blit 2", time.time(),"->"
         surfold.set_alpha(a2)
         surf.blit(surfold, (0, 0))
-        
-        #surf.fill((a2, a2, a2), None, BLEND_RGB_MULT)
-        #print time.time()
-        
+                
         return surf, 0, 0
     
     def effectZoomOut(self, surf, surfold, surfnew, v):
         w = int(r.width * (1 - v))
         h = int(r.height * (1 - v))
         
-        #print "scale", time.time(),"->",
         s = pygame.transform.scale(surfold, (w, h))
-        #print time.time()
         
-        #print "blits", time.time(),"->"
         surf.blit(surfnew,(0,0))
-        #print 1,time.time()
-        surf.blit(s, (r.width / 2 * (v), r.height / 2 * (v)))
-        #print 2,time.time()
+
+        surf.blit(s, (r.width / 2 * (v), r.height / 2 * (v)))        
         
         return surf, 0,0
     
         
         start = time.time()
         end = start + self.duration
-        
-        
-        
+         
         exitnext = False
         now = time.time()
+        
+        # The animation buffer
+        #surf = pygame.Surface(self.surf1.get_size(), )
+        
         while True: 
             t = now - start
             
                 self.render_callback(s)
             
             for effect, tween in effect_tween:
-                #print "effect", time.time(),"->",
                 v = tween(t, 0, 1, self.duration)
-                surf = pygame.Surface(self.surf1.get_size(), )
-                surf, x, y = effect( surf, s, self.surf2, v )
-                s = surf
-                #print time.time()
+                _surf, x, y = effect( self.screen, s, self.surf2, v )
             
-            #print "blit", time.time(),"->",
-            self.screen.blit(s, (x,y))
-            #print time.time()
+            #self.screen.blit(surf, (x,y))
             
             pygame.display.flip()
-            #print "tick", time.time(),"->",
+            
             self.clock.tick(30)
             
             if exitnext:
             
             #fps += 1
         
-        #print "fps"
         
 class TextCache(object):
     """ Handles text rendering and caches the surfaces of the texts for speed.
         menu2.bg = bg2
         
         def render_callback(surf): 
-            # We'll need to update the logo in the background, 
-            # which depends on the tick counter.
-            #tics = pygame.time.get_ticks()
-            #self.sysdata.ticdiff = tics - self.sysdata.tics
-            #self.sysdata.tics = tics
-            
-            #self.mainbg.update()
-            #self.screen.blit(self.mainbg.surface, (0, 0))
-            #surf.blit(self.bg.surface, (0, 0))
-            #surf.set_alpha(96)
-            
-            #bg1.update()
-            #bg2.update()
             menu1.update()
             menu2.update()
         
         # Blocks for the duration of the animation
         effect = [e.effectSlideLeftReplace, e.effectSlideRightReplace, e.effectFadeTo][effect]
         e.do([
-              (effect, lambda t, b, c, d, s=1.01:e.tweenEaseInOutSine(t, b, c, d, s)),
-              (e.effectFadeTo, e.tweenEaseOutSine),
+              (effect, lambda t, b, c, d, s=0.5:e.tweenEaseInOutSine(t, b, c, d, s)),
+              #(e.effectFadeTo, e.tweenEaseOutSine),
               ], 0.5)
         
         # The animation completed.

symbian/app/pygame_main.cpp

 
 #ifndef PYGAME_MAIN_SCRIPT_PATH
 #define PYGAME_MAIN_SCRIPT_PATH "\\data\\pygame\\pygame_main.py"
-#define PYGAME_LAUNCHER_PATH    "\\data\\pygame\\launcher\\pygame_launcher.pyc"
+#define PYGAME_LAUNCHER_PATH    "\\data\\pygame\\launcher\\pygame_launcher.py"
 #endif
 static const char* gPygameMainScriptPath[2] = {
 		PYGAME_MAIN_SCRIPT_PATH,
 	// Execute the main script
 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2
 	CSPyInterpreter* interp = CSPyInterpreter::NewInterpreterL();
-#else	
+#else
 	SPy_DLC_Init();
 	SPy_SetAllocator(SPy_DLC_Alloc, SPy_DLC_Realloc, SPy_DLC_Free, NULL);
 #endif
 	Py_Initialize();
-	
+
 	// Add built-in pygame modules
 	PyImport_ExtendInittab(_PyGame_Inittab);
-			
+
 	LOGMAN_SENDLOG( "Entering interpreter");
 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2
 	TInt result = interp->RunScript(1, gPygameMainScriptPath);
-#else	
-	
+#else
+
 	LOGMAN_SENDLOGF("Number of args:%d", argc);
 	if(argc > 1){
 		gPygameMainScriptPath[1] = argv[1];
 	}
-	
+
 	LOGMAN_SENDLOGF8( "Opening file:%s", gPygameMainScriptPath[0] );
 	FILE *fp = fopen(gPygameMainScriptPath[0], "r");
 	if (!fp) {
 		LOGMAN_SENDLOG( "Failed to open main script" );
 		return -1;
 	}
-	
+
 	// This allows us to retrieve the path of the main script in Python from sys.argv[0]
 	PySys_SetArgv(2, (char**)gPygameMainScriptPath);
-	
+
 	int result = PyRun_SimpleFile(fp, gPygameMainScriptPath[0]);
 	fclose(fp);
 #endif
-	
+
 	LOGMAN_SENDLOGF( "Interpreter result:%d", result )
 
-#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2	
+#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2
 	PyEval_RestoreThread(PYTHON_TLS->thread_state);
 	Py_Finalize();
 	delete interp;
 	Py_Finalize();
 	SPy_DLC_Fini();
 #endif
-	
+
 	SDL_Quit();
 	return result;
 }

symbian/app/pygame_main.py

 
 THISDIR = os.path.dirname( __file__ )
 sys.path.append( os.path.join( THISDIR, "libs") )
+sys.path.append( os.path.join( THISDIR, "libs", "pygame.zip") )
 
 if len(sys.argv) < 2:
     path_to_app = os.path.join( THISDIR, "launcher", "pygame_launcher.py" )

symbian/how_to_build.txt

 
 Create symbian/deps directory
 
+Get PyS60 SDK from Maemo Garage
+- https://garage.maemo.org/frs/?group_id=854&release_id=2673
+-- Unzip the stuff to your Symbian epocroot
+
+Get PyS60 packaging tool
+- Use the installer or get the tar.gz package.
+-- Copy the PythonForS60 folder to 'deps'
+
+
 Checkout ogg to symbian/deps/ogg
 - IMPORTANT: Revision 7524
 - SVN: http://svn.xiph.org/trunk/ogg 
 
 Get SDL for Series60
 - Available at: http://koti.mbnet.fi/mertama/sdl.html
-- Follow the instructions and copy the pathced SDL S60 folder to symbian/deps/SDL
+- Follow the instructions and copy the patched SDL S60 folder to symbian/deps/SDL
 
 Get SDL_mixer to symbian/deps/SDL_mixer
 - http://www.libsdl.org/projects/SDL_mixer/

test/midi_test.py

 
 
 
-    def test_get_default_input_device_id(self):
+    def test_get_default_input_id(self):
 
         # __doc__ (as of 2009-05-19) for pygame.midi.get_default_input_device_id:
 
           # Note: in the current release, the default is simply the first device
           #     (the input or output device with the lowest PmDeviceID).
 
-        c = pygame.midi.get_default_input_device_id() 
+        c = pygame.midi.get_default_input_id() 
         self.assertEqual(type(c), type(1))
         self.failUnless(c >= 0)
 
 
-    def test_get_default_output_device_id(self):
+    def test_get_default_output_id(self):
 
         # __doc__ (as of 2009-05-19) for pygame.midi.get_default_output_device_id:
 
           # Note: in the current release, the default is simply the first device
           #     (the input or output device with the lowest PmDeviceID).
 
-        c = pygame.midi.get_default_output_device_id() 
+        c = pygame.midi.get_default_output_id() 
         self.assertEqual(type(c), type(1))
         self.failUnless(c >= 0)
 
           # 
           # If the id is out of range, the function returns None.
 
-        an_id = pygame.midi.get_default_output_device_id() 
+        an_id = pygame.midi.get_default_output_id() 
         interf, name, input, output, opened = pygame.midi.get_device_info(an_id)
+        #print interf
+        #print name
+        #print input, output, opened
+
         self.assertEqual(output, 1)
         self.assertEqual(input, 0)
         self.assertEqual(opened, 0)
 
 
-        an_in_id = pygame.midi.get_default_input_device_id() 
+        an_in_id = pygame.midi.get_default_input_id() 
         interf, name, input, output, opened = pygame.midi.get_device_info(an_in_id)
         self.assertEqual(output, 0)
         self.assertEqual(input, 1)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.