====== 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()