====== Python For Maemo 5 Info ====== The python used in the Nokia N900 is known as [[http://pymaemo.garage.maemo.org/|PyMaemo]]. It is basically the normal python, with additional device related commands. API Documentation (non-pythonic): [[http://maemo.org/development/sdks/maemo_5_api_documentation/|Maemo 5 Api Docs]] Python Tutorials: [[http://temporaryland.wordpress.com/2011/01/26/python-for-newbies/|Python for newbies]] It is also possible to access C APIs that don't have Python bindings. However, this can bring some interesting problems. Not recommended, as most of the maemo APIs should work just fine with Python. However, check [[http://wiki.maemo.org/PyMaemo/Accessing_APIs_without_Python_bindings|Accessing APIs without Python bindings]] for more info. ===== Playing Sounds ===== N900 can play sounds with two different ways - Either using gstreamer or pygame. This example is made with pygame as it provides a higher-level API and requires less magic words ;-) Pygame documentation can be found behind the following link: [[http://www.pygame.org/docs/|PyGame Documentation]] The sound file used in this example: {{:maemo:button-4.wav.tar.gz|Sound file}} Here is a proper Object-Oriented implementation of a Player that can load and play sound files. I suggest creating a list of sound objects that are loaded with this player and then playing those when needed (faster than opening a file for playback each time separately). """ August 9, 2011 @author: Janne Parkkila @email: japskua@gmail.com @summmary: This file contains code for playing music/sounds on N900 with Python programming language. This implementation uses pygame instead of gstreamer """ import pygame class Player(object): def __init__(self): """ @summary: The Constructor class """ pygame.mixer.quit() pygame.mixer.init() pygame.init() def Play(self, sound): """ @summary: This function is used to play the given sound @param sound: The sound to be played @type sound: pygame sound object """ sound.play() def Load(self, filename): """ @summary: This function loads the given filename into a pygame readable sound object @param filename: The path to the file to be loaded @type filename: String @return: Loaded pygame music object @rtype: pygame Sound """ return pygame.mixer.Sound(filename) if __name__ == "__main__": # Initialize the player player = Player() # Load the soundfile with the player sound = player.Load("button-4.wav") # Play the file player.Play(sound) However, if you want to make something better yourself, here is the basic simple version of the same thing import pygame pygame.mixer.init() pygame.init() sound = pygame.mixer.Sound("button-4.wav") sound.play() ===== Using Microphone ===== This code snippet uses gstreamer to record voice through the phone microphone. Notice that there is a small lag on starting the recording and after stopping the record. This is purely related to gstreamer and should be taken into account when developing applications. So, don't wait zero response time with this code :-P **Note: If this doesn't work, you are probably missing some gstreamer related plugins** Get them with: sudo gainroot apt-get install gstreamer0.10-alsa gstreamer0.10-flac gstreamer0.10-plugins-good-extra #!/usr/bin/env python # This is the MIT license: # http://www.opensource.org/licenses/mit-license.php # Copyright (c) 2009 Digital Achievement Incorporated and contributors. # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # """ @summary: This file contains the data for SoundRecorder on Nokia N900 using Python and gstreamer. The code is based on the source by Digital Achievement and is available from: http://achievewith.us/public/articles/2009/01/28/using-gstreamer-and-python-to-record-audio @author: Janne Parkkila (the modified Object Oriented Version) @email: japskua@gmail.com @requires: gstreamer0.10-alsa, gstreamer0.10-flac, gstreamer0.10-plugins-good-extra """ from optparse import OptionParser import dbus import gst import sys import time class SoundRecorder(object): """ @summary: This is the SoundRecorder class that handles locating the microphone and capturing voice from the mic. Currently uses somewhat "dirty" method of calling gstreamer via command line, but works pretty well nonetheless :-D """ mic = None def __init__(self): """ @summary: The Constructor class, that searches for the microphone on initialization """ bus = dbus.SystemBus() hal_manager = bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager") hal_manager = dbus.Interface(hal_manager, "org.freedesktop.Hal.Manager") print hal_manager devices = hal_manager.FindDeviceStringMatch("alsa.type", "capture") identifiers = [] for dev in devices: device = bus.get_object("org.freedesktop.Hal", dev) card = device.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device") if card["alsa.card"] not in identifiers: print "%d. %s" % (card["alsa.card"], card["alsa.card_id"]) identifiers.append(card["alsa.card"]) self.mic = identifiers[0] def Record(self, destination): """ @summary: Records the audio with the microphone and saves to the given destination @param destination: The destination where to save the captured voice @type destination: String """ pipeline = gst.parse_launch("""alsasrc device=hw:%d ! audioconvert ! level name=recordlevel interval=10000000 ! audioconvert ! flacenc ! filesink location=%s""" % (self.mic, destination)) pipeline.set_state(gst.STATE_PLAYING) print "recording, press enter to stop" sys.stdin.readline() pipeline.set_state(gst.STATE_NULL) time.sleep(5) if __name__ == "__main__": # This is used if the code is run straight from the command line recorder = SoundRecorder() recorder.Record("output.wav") ===== Using Camera ===== This code uses the N900's camera to take picture. It is not very sophisticated, as the back camera does not use flash (at least with the current implementation). Also, not that the Python does not really support taking pictures, thus requiring user to take pics by calling gstreamer through command line. This is an evil hack and will steal your soul. **You can only use this as a super user** Which gives me SUPER POWERS!! MUAHAHHAAHAHAA!!! so please, before running any camera python apps (at least based on my code) make sure you do sudo gainroot python camera.py (or in scratchbox) fakeroot python2.5 camera.py """ August 9, 2011 @author: Janne Parkkila @email: japskua@gmail.com @summary: This file contains code for taking pictures with the front or the back camera of the nokia N900. The file provides python access to the camera but really just uses command line to take picture. @note: PyMaemo has no possiblity to capture pictures, thus this gstreamer capture is used via command line. This requires super user rights, so if you are using this file you can only take pictures with as a sudoer. ALSO! MAKE SURE THE CAMERA LID IS OPEN WHEN TAKING THE PICTURE!!! :-P """ import sys import gst import os class Camera(object): """ @summmary: This is the camera object that is capable of capturing pictures with either the front or the back camera of the device """ back = None front = None def __init__(self): """ @summary: The Constructor """ self.back = "gst-launch v4l2src device=/dev/video0 num-buffers=1 ! ffmpegcolorspace ! jpegenc ! filesink location=" self.front = "gst-launch v4l2src device=/dev/video1 num-buffers=1 ! ffmpegcolorspace ! jpegenc ! filesink location=" def TakePicture(self, camera, filename): """ @summary: The function for taking pictures with the camera @param camera: The camera to be taken pictures with @type camera: String, either "FRONT" or "BACK" @param filename: The path to the file where to save the taken picture, without the filetype suffix. @type filename: String """ photo = None if camera == "FRONT": photo = self.front + filename + ".jpg" elif camera == "BACK": photo = self.back + filename + ".jpg" else: print "Error, camera should be either FRONT or BACK" os.system(photo) # If this program is executed as itself if __name__ == "__main__": camera = Camera() camera.TakePicture("FRONT", "frontcam") camera.TakePicture("BACK", "backcam") ===== Bluetooth ===== Bluetooth stuff here ===== Using Accelerometer ===== Download this source from here: {{:maemo:accelerometer.py.tar.gz|Accelerometer.py}} """ Created August 9, 2011 @author: Janne Parkkila @contact: japskua@gmail.com @summary: This file contains class implementation on connecting to maemo dbus and receiving accelerometer data """ import dbus class Accelerometer(object): """ @summary: This class is used to get accelerometer data from the dbus """ bus = None accelerometer = None def __init__(self): """ @summary: The Constructor for the class """ self.bus = dbus.SystemBus() self.accelerometer = self.bus.get_object("com.nokia.mce", "/com/nokia/mce/request", "com.nokia.mce.request") def getData(self): """ @summary: This function returns the data of the accelerometer @return: orientation, stand, face, x, y, z @rtype: list """ return self.accelerometer.get_device_orientation() def displayData(self): """ @summary: This function is just used to display data """ orientation, stand, face, x, y, z = self.getData() print "Orientation: ", orientation print "Stand: ", stand print "Face: ", face print "X: ", x print "Y: ", y print "Z: ", z # This is only if we want to run the accelerometer test straight from the command line if __name__ == "__main__": print "Starting the Accelerometer test" accel = Accelerometer() accel.displayData() ===== Using Location API ===== Note: The python location might not be installed on the device. In this case, you need to install it with apt-get install python-location **IMPORTANT TO NOTICE** The GPS on the N900 is not very fast! Acquiring a signal can take a great amount of time. Thus it is just recommended to simulate this in some other manner. The probability of receiving a signal in the basement is really small, so please, don't waste too much of your precious time with this. More info on location API with pyMaemo can be found from: * [[http://wiki.maemo.org/PyMaemo/Using_Location_API| PyMaemo Location API at maemo wiki]] * [[http://pymaemo.garage.maemo.org/python_location_manual/location.html#| PyMaemo Location bindings]] The following file is brutally ripped from the Maemo wiki: import location import gobject def on_error(control, error, data): print "location error: %d... quitting" % error data.quit() def on_changed(device, data): if not device: return if device.fix: if device.fix[1] & location.GPS_DEVICE_LATLONG_SET: print "lat = %f, long = %f" % device.fix[4:6] # data.stop() commented out to allow continuous loop for a reliable fix - press ctrl c to break the loop, or program your own way of exiting) def on_stop(control, data): print "quitting" data.quit() def start_location(data): data.start() return False loop = gobject.MainLoop() control = location.GPSDControl.get_default() device = location.GPSDevice() control.set_properties(preferred_method=location.METHOD_USER_SELECTED, preferred_interval=location.INTERVAL_DEFAULT) control.connect("error-verbose", on_error, loop) device.connect("changed", on_changed, control) control.connect("gpsd-stopped", on_stop, loop) gobject.idle_add(start_location, control) loop.run()