Join Now

It all started innocently enough. The notebook didn't fit in my pocket, and my N93 was already there.

Off to Java One

kevin_s2f | 03 May, 2008 01:48

I'm about to pack and head off to JavaOne. If you're coming to the show, be sure to stop by Nokia booth 818 and say Hi. I just updated the Continue the Conversation post so you know where the conversations are happening whether you're in San Francisco connecting after hours, or at home connecting remotely.

 

Ask for Anina!

kevin_s2f | 22 April, 2008 01:48

Anina is featured in the Transformation Age documentary debuting on PBS stations in the US this week. Her work in fashion reporting using Nokia technology is featured in the discussion about transforming the design of organizations. You can preview her segment here.

Here's the current schedule. If your local station has not yet committed to airing the story, please call them. If you are a member of your local PBS station don't forget to mention it when you call. You get more than a tote bag when you pledge, you get a voice in how your station is run. That's what the Public in Public Broadcasting is supposed to be all about.

Continue the Conversation, Live from Java One

kevin_s2f | 16 April, 2008 23:40

We want to help you continue the conversations you start at JavaOne, after hours and after the conference. We have two live Talk to the Guru sessions scheduled online during the conference, one on the new Java API for Location Based Services (JSR 293) and one on a new SVG tool chain for JSR 226. Other conversations cover Java on Series 40, special considerations when designing services for Africa, and anything else you want to talk about including the nine sessions with Nokia speakers. 

It was good seeing so many of you at the conference. To those I talked to, and those who could not make it to San Francisco, I hope you continue the conversation online.

Update: download code samples and presentations from the conference here.

If you are new to the Forum Nokia online community, please register here so you can join the conversation.

  • Conversation 1: LBS Goes Social.
    With JSR 293, Location Based Services can become a lot more about us, and a lot less about me. I started a conversation with Gurus from Nokia, Navteq, and uLocate about the future of social Location Based Services. Check out the video, join us at Java One, then
    join us for a live Talk to the Gurus session in the Discussion Boards on Friday, May 9, at 9:00 AM in San Francisco. Time in your area.

Thanks for a great conversation to:

Updated: new conversations added April 29 - May 2 

  • Conversation 2: Build Richer Java UIs
    A new tool chain makes it easy to build richer UIs for your mobile applications and content. Seamless integration among Adobe Illustrator, Ikivo Animator, Sun Netbeans, and Nokia SDKs allows designers to focus on the UI and graphics, freeing developers to focus on application logic. Check out this screen cast, then bring your questions to guru Mike Garrett with Ikivo, live from Java One, for a great Talk to the Guru session.
    Wednesday, May 7, 9:00 AM San Francisco Time in the Discussion Boards. Time in your area.
  • Conversation 3: Java on Series 40 Platform
    Nokia estimates it has cumulatively shipped hundreds of millions of devices powered by the Series 40 Platform. Our platform experts will be on the JavaOne show floor demonstrating the latest tools and technology and talking with developers. Continue the conversation in this thread.
  • Conversation 4: Design for Africa
    Nokia Sr. UI Designer JD Moore discusses key design techniques for services in Africa at in his presentation Regional and Cultural Accessibility fo the Java Platform, Micro Edition (Java ME Platform): Africa. Continue the conversation in this thread.

  • Conversation 5: Everything Else
    The best conversations are seldom planned. Continue the unexpected here.

 

Live WRT Gurus Tues 17:00 UK Time Time

kevin_s2f | 01 April, 2008 02:04

My brain is filling up fast. I'm in the second Nokia Developer Day training in Las Vegas, and the presentations have been excellent.

Wai Seto ran a great session on WRT, and if you weren't lucky enough to be in the room with him join him online tomorrow (Tuesday) at 9:00 California time (17:00 in the UK). Note an earlier notice, from me Cry got the time conversion wrong for UK Summer time.

Joining Wai will be Kelvin Chong, the Chief Architect at Plusmo. He has more experience with commercial WRT Widgets than just about anybody else on the planet. More on Plusmo's success in the space here.

 

Talk to Widget Gurus

kevin_s2f | 22 March, 2008 01:11

We have two great live sessions on tap for developers with questions about Web Runtime in general, and S60 Web Widgets in particular.

Both discussions take place in the Web Runtime Forum (Discussion Board).

Developers in APAC time zones get the first opportunity. Live from the Singapore Code camp join Zhen Zhen from Nangyang Polytechnic on March 24.

Then, live from the second Nokia Developer Day, join Plusmo Chief Architect Kelvin Chong and Nokia Senior Architect Wai Seto on April 1. This session will be more convenient for developers in Western Europe and the Americas.

Details on eLearning, SDK, and other available online prep work are covered in this thread. 

Last month's live session with Navteq LBS gurus is now the most-read thread in LBS.

We're still confirming Gurus for Flash Lite, so if you have nominations post them here. 

 

Video Guide to LBS Challenge in APAC

kevin_s2f | 27 February, 2008 23:54

For those of you who can't make it to the Singapore code camp tomorrow, here's a video by Steven Si, the Global Lead Technical Consulting Partner and Developer Program for Navteq, discussing what you need to know to submit an entry to the contest.  View it and then join the discussion here.

LBSChallenge_Si.wmv

 

 

Live Answers on Maps and Navigation

kevin_s2f | 27 February, 2008 18:52

Just a reminder for those interested in LBS services that we have a live on-line session scheduled tomorrow with Ejaz Iqbal, North America Technical Consulting
Partner and Developer Program manager for Navteq. Ejaz will be available live from 16:00 - 17:00 GMT (08:00 - 09:00 California) to talk about getting started with Navteq data and tools, including available data formats, sample data set availability, and tooling.

The live session will take place in this DiBo thread, so you do not have to use any fancy registration process. Just show up, login with your Forum Nokia username, and ask away.

If you can't make the live session, ask your question now or shortly after the session. Ejaz will return on Friday to answer questions, especially questions that come from the attendees of the LBS Code Camp in Singapore.

I hope to see you tomorrow. 

Unique, sortable filenames with Python

kevin_s2f | 31 July, 2007 01:32

I finally got some time to work on this code. I've accomplished some relatively minor tasks:

I thought through the best way to name and organize files. Time-stamping is a good way to pull unique names on the fly, and that's how LFD does it in the camera-and-viewfinder example over in the Wiki. 

 
     import time
     ctime = time.localtime()
     picName = str(ctime[0])+str(ctime[1])+str(ctime[2])+str(ctime[3])+str(ctime[4])+str(ctime[5])

Working with that assignment a bit, I didn't like the way it treated months and days -- January 11 comes out the same as November 1.

So I used formatting like this:

     import time
     ctime = time.localtime()
     fileNameRoot = '%4i%02i%02i%02i%02i%02i' % ((ctime[0]), (ctime[1]), (ctime[2]), (ctime[3]), (ctime[4]), (ctime[5]))

This allows me to assign filenames by the time when the first version was created, update the files as necessary (by adding more audio to a recording, for example,) and still reliably sort by first creation.

This lead me relatively quickly to split the image and audio files into separate directories. Using the same root file names for both the image files and audio files lets me put them back together easily (before I dig into the database engine). Separating them into two directories allows me to fill a listbox with elements drawn from one directory and not have to manually eliminate duplicates.

So that leaves me with the code below. Next step is to factor out the construction of the primary listbox so I can re-build it after adding a record. 


import e32, appuifw, time
import cameraandview

debug = 1
picPath = u'e:tmjimages' # remember first '' escapes the character.
audPath = u'e:tmjaudio'


# ToDo: add code to catch and process SymbianError -12 KErrPathNotFound if path does not yet exist.

def takepic(aPath, aFilename):
    import camera
    # save UI elements
    oldBody = appuifw.app.body
    oldExit = appuifw.app.exit_key_handler
    oldFocus = appuifw.app.focus
    oldMenu = appuifw.app.menu
    oldScreen = appuifw.app.screen
    oldTitle = appuifw.app.title
    if debug: appuifw.app.title = u'Let us take a picture here.'
    im = camera.take_photo()  # use all default values -- eventually this fn will change *.body into canvas control for viewfinder
    im.save(aPath + aFilename)
    #restore UI elements
    appuifw.app.body = oldBody
    appuifw.app.exit_key_handler = oldExit
    appuifw.app.focus = oldFocus
    appuifw.app.menu = oldMenu
    appuifw.app.screen = oldScreen
    appuifw.app.title = oldTitle
   

def recordaudio(aPath, aFilename):
   import e32, audio
 
   if debug: appuifw.note(u'hello from inside recordaudio',)
   s = audio.Sound.open(aPath + aFilename) # if file exists, append sound to end
   s.record()  # start recording
   e32.ao_sleep(5)  # do if for 5 seconds
   s.stop() # stop recording
 
 
   # the file is now created, ready to be played
   # s.play()       

def handle_selection():
    appuifw.note(u'hello from inside handle_selection',)
    index = lb.current()
    code = choices[index][1]
    lb.set_list([u'Please wait...'])
    if code == 'new':
        # construct unique name root that's easily sortable by time.
        ctime = time.localtime()
        fileNameRoot = '%4i%02i%02i%02i%02i%02i' % ((ctime[0]), (ctime[1]), (ctime[2]), (ctime[3]), (ctime[4]), (ctime[5]))
        if debug: appuifw.note(u'here is where we process a new experience', 'info')
        picName = fileNameRoot + u'.jpg'
        takepic (picPath, picName)
        if debug: appuifw.note(u'back to handle_selection after takepic',)
        audName = fileNameRoot + u'.amr'
        recordaudio (audPath, audName)
       
    elif code == 'comment':
        if debug: appuifw.note(u'here is where we add a comment', 'info')
        fileNameRoot = choices[index][0]
        fileNameRoot = fileNameRoot[8:] # strip off 'comment ' from UI
        audName = fileNameRoot + u'.amr'
        recordaudio (audPath, audName)
    else:
        appuifw.note(u'no valide code detected', 'info')
    lb.set_list(choices_labels)

def handle_add():
    pass 

def handle_delete():
    pass

def exit_key_handler():
    app_lock.signal()

# todo -- need to factor this out so handle_selection / new can re-build the lb
choices =[(u'New experience', 'new')]
picFiles = []
for item in os.listdir(picPath):
    if not item[0] == '_': picFiles.append(unicode(item[:-4])) # strip off file extension

picFiles.sort() # just in case it does not come from directory already sorted
picFiles.reverse() # and show last addition first

for item in picFiles:
    choices.append( (u'Comment ' + item, 'comment') )  # todo strip off extra chars b4 displaying
 
choices_labels = [x[0] for x in choices]
lb = appuifw.Listbox(choices_labels, handle_selection)

appuifw.app.title = u'Tasty Multimedia Journal'
appuifw.app.body = lb
appuifw.app.menu = [(u'Add new item', handle_add),
                    (u'Delete item', handle_delete)]
appuifw.app.exit_key_handler = exit_key_handler
if debug: appuifw.note(u'prepare to lock',)
app_lock = e32.Ao_lock()
if debug: appuifw.note(u'and now we wait',)
app_lock.wait()

Multi-view UI Design in Python for S60 -- this works

kevin_s2f | 13 July, 2007 02:26

Thanks to Lfd over in the PyS60 Forum here, I now have a better handle on view switching in Python. Now, when I execute a call-back function that needs to change attributes of the UI (from a listbox to canvas, for example) it's a simple task of wrapping the function with some state preservation and restoration code. 

What you see here is simple assignments, but exanding on Lfd's suggestion one could easily package all the attributes into a state tuple, push the tuple on a view stack, and pop views off the stack as needed.

Here is the simple case:

def takepic(filename):
    import camera
    # save UI elements
    oldBody = appuifw.app.body
    oldExit = appuifw.app.exit_key_handler
    oldFocus = appuifw.app.focus
    oldMenu = appuifw.app.menu
    oldScreen = appuifw.app.screen
    oldTitle = appuifw.app.title
    appuifw.app.title = u"Let us take a picture here."
    im = camera.take_photo()  # use all default values -- eventually this fn will change *.body into canvas control for viewfinder
    im.save(u'e:test.jpg')
    #restore UI elements
    appuifw.app.body = oldBody
    appuifw.app.exit_key_handler = oldExit
    appuifw.app.focus = oldFocus
    appuifw.app.menu = oldMenu
    appuifw.app.screen = oldScreen
    appuifw.app.title = oldTitle

Multi-view UI design in Python for S60

kevin_s2f | 11 July, 2007 02:06

What I started today expecting to be hard turned out to be easy, and what I expected to be easy I still haven't figured out ;-)

I began the day reading and learning from Lfd's code for taking a picture using the viewfinder. Since I want to call it from several places in my app, I want to load it as a library. I wrote a simple calling script, and installed Lfd's code in E:Pythonlib (note -- NOT E:Pythonlibs ). That all worked easily enough, so before I dug into modifying the camera code I wanted to embed the calling routine into my primary script.

That's where I ran into something that I still haven't figured out. The core of my simple UI right now is 10 lines of code that build a list box UI. 

lb = appuifw.Listbox(choices_labels, handle_selection)

old_title = appuifw.app.title
appuifw.app.title = u"Tasty Multimedia Journal"
appuifw.app.body = lb
appuifw.app.menu = [(u"Add new item", handle_add),
                      (u"Delete item", handle_delete)]
appuifw.app.exit_key_handler = exit_key_handler
app_lock = e32.Ao_lock()
app_lock.wait()
appuifw.app.title = old_title

The event handler is a function defined earlier in the script.
def handle_selection():
    appuifw.note(u"hello from inside handle_selection",)
    index = lb.current()
    appuifw.note(u"hello from after index=lb.current",)
    code = choices[index][1]
    lb.set_list([u"Please wait..."])
    if code == "new":
        appuifw.note(u"here is where we process a new experience", 'info')

    elif code == "comment":
        appuifw.note(u"here is where we add a comment", 'info')
    else:
        appuifw.note(u"no valide code detected", 'info')
        lb.set_list(choices_labels)


Now here's the problem. Since I'll need to re-build the home screen upon returning from taking a picture (which uses Canvas), I factored out those 10 lines of code into a function, and simplified my "main" script into a single statement that calls the function.

def build_homescreen():
    appuifw.note(u"entered buildhomescreen fn",)
    lb = appuifw.Listbox(choices_labels, handle_selection)
    old_title = appuifw.app.title
    appuifw.app.title = u"Tasty Multimedia Journal"
    appuifw.app.body = lb
    appuifw.app.menu = [(u"Add new item", handle_add),
                                           (u"Delete item", handle_delete)]
    appuifw.app.exit_key_handler = exit_key_handler
    app_lock = e32.Ao_lock()
    app_lock.wait()
    appuifw.app.title = old_title
build_homescreen()

Turns out that embedding the Listbox build in a function breaks the event handler, as the event handler no longer seems to have access to the pointer to the selected listbox element. I suspect I have a scope problem that I don't yet understand.

I'm over on the discussion boards trying to figure this out. If you have some insight into what I'm missing, or if you can recommend a resource that shows a good multi-view UI implementation, please point me to it. Either by posting a comment to this entry, or by replying to the DiBo question here.

UI in Python using listbox

kevin_s2f | 10 July, 2007 00:57

I want the tasting journal application to open with a UI that presents two simple options:
  • record an experience
  • view past experiences
The easiest way that I’ve seen to do that in PyS60 is with a listbox control. The UI in PyS60 is implemented in the appuifw module, which according to the documentation available at sourceforge:
 
The appuifw module offers an interface to the S60 UI application framework. Figure 5.1 provides an
overview of the Python for S60 environment for UI application programming.
Note: The services of this interface may only be used in the context of the main thread, that is, the
initial thread of a UI application script.
 
So whether you are new to Python (like me) or just new to Python on S60, this module will be new to you. As I was downloading and installing the execution environment on the N93 and the SDK on my PC, I also downloaded and extracted the source files. Unzipping that package revealed a hidden treasure of example files that I found in directory …srcextrasexamples*.py. Three of the examples in that directory provide good UI overviews – I began with GUI_exaple_2.py, extracted all the peripheral material, and came up with a basic skeleton of a UI for the journal: a list box with two options. I posted that skeleton in the Wiki here.
 
Then I went in to the Wiki to find the most basic multimedia functionality – quickly snap a pic (here)  and record a track (here).  Inserting those snippets into the UI skeleton results in this code:
 
import e32
import appuifw
 
choices =[(u"New experience", "new"),
          (u"Add comment", "comment")]
choices_labels = [x[0] for x in choices]
 
def takepic(filename):
    import camera
    im = camera.take_photo() # use all default values
    im.save(filename)
   
 
def recordaudio(filename):
   import e32, audio
 
   print(u"Hello from inside recordaudio fn")
   s = audio.Sound.open(filename) # if file exists, append sound to end
   s.record() # start recording
   e32.ao_sleep(5) # do if for 5 seconds
   s.stop() # stop recording
 
 
   # the file is now created, ready to be played
   s.play()       
 
def handle_selection():
    index = lb.current()
    code = choices[index][1]
    lb.set_list([u"Please wait..."])
    if code == "new":
        appuifw.note(u"here is where we process a new experience", 'info')
        takepic (u"e:test.jpg")
        recordaudio (u"e:test.amr")       
       
    elif code == "comment":
        appuifw.note(u"here is where we add a comment", 'info')
        recordaudio (u"e:test.amr")
    else:
        appuifw.note(u"no valide code detected", 'info')
    lb.set_list(choices_labels)
 
def handle_add():
    pass 
 
def handle_delete():
    pass
 
def exit_key_handler():
    app_lock.signal()
 
lb = appuifw.Listbox(choices_labels, handle_selection)
 
old_title = appuifw.app.title
appuifw.app.title = u"Tasty Multimedia Journal"
appuifw.app.body = lb
appuifw.app.menu = [(u"Add new item", handle_add),
                    (u"Delete item", handle_delete)]
appuifw.app.exit_key_handler = exit_key_handler
 
app_lock = e32.Ao_lock()
app_lock.wait()
 
appuifw.app.title = old_title
 
Next steps:
  • Work with a more sophisticated image capture script  (here) which provides viewfinder functionality.
  • Control media filenames to associate audio tracks with the images they describe.

Stable Python shell released for N93 and other S60 devices

kevin_s2f | 06 July, 2007 21:06

Jukka and the PyS60 team just released version 1.4.0 of Python for S60. According to  Jukka's announcement "The release is officially Nokia signed. ...there is no longer a need for a separate unsigned-freedevcert version of this package." 

Versioning in the PyS60 project is such that even numbers of minor releases denote stable releases; odd numbers denote development releases. Thus the 1.3.2x releases we have been working with were development, and 1.4.0 is stable. That's why they went ahead and signed the distribution package.

Get it here.

Free beginner tools for Python on N93, N95, and other Nokia S60 devices

kevin_s2f | 06 July, 2007 02:26

Wow, what a week. Still a little bit jet-lagged from last week’s return from Singapore, but finally got a chance to really dig into this project. I now have my basic tool set installed, I have a repeatable work flow that works for me, I located some foundation documentation that explain things to beginners like me that seem to be common knowledge among the experienced Python developers, and with the help of some of the experts on the discussion boards I worked through an application structuring issue that didn’t seem to be common knowledge among those working with PyS60 on 3rd Edition devices.
 
I apologize for not posting threads all through this process, but I really needed to just keep my head down and work things through for a while. Python on S60 appeals to me because everybody tells me how easy it is. Well, it’s been a lot of years since I’ve personally coded anything, and between years of work on the marketing side of technology and a bit of foggy-brain syndrome from the travel, I really struggled for a few days to get traction. I know me, and posts during this time were likely to come across as, well, less than useful. More like whining. And of no use to the wider community at all.
 
Now that I’ve gotten to the other side of that struggle, I agree with the experts who say how easy and fun PyS60 can be. This morning, when I got my first script running, taking pictures, and recording audio, I actually said out loud "this is fun!". PyS60 has converted my N93 from a great device that does what Symbian and Nokia software engineers decided it should do, to a platform that I can make do what I want it to do. That's the fun part.

Now that I understand some of the basics the experts sometimes forget to tell a newcomer about, I hope I can communicate them to others who want to play.
 
Let me start with the details of the development environment I have set up for myself.
 
First, I needed a Python emulator for S60 / N93. That begins with the Symbian/C++ SDK appropriate for my device. The N93 is a S60 3rd Edition device (not Feature Pack 1 or Feature Pack 2). If you are unsure about yours, check the device specs.
 
AFTER installing the C++ SDK, I downloaded and installed the Python SDK appropriate for my device from here. In this case all 3rd Edition devices are created equal – no SDK difference between 3rd Edition, Feature Pack 1, or Feature Pack 2. The only choice was compiler tool chain – I chose ARMV5.
 
Follow the release notes that tell you to unzip the files from the Python SDK into the same directory chosed for the C++ SDK.
 
Then launch the emulator, and you’ll see Python as an application available under “Installat.” on the main grid. Choose Options/Run script and you’ll see some sample python scripts that ship with the SDK.

Open installations folder first ...

Launch the emulator and select the installations folder.

Python runs from here

Then you can run the Python interpreter.
 
Tip: the sample scripts you see when running the interpreter in the emulator provide the key to using the emulator for your Python development. Use PC Search to find all the places the script ball.py is found on your machine. You’ll find one directory that looks something like c:Symbian9.1S60_3rd_MREpoc32winscwcpython . If you place your python script file in that directory, you’ll be able to run it in the emulator.
 
Tip: there are more sample files in the Python SDK than you will see in the emulator. Whereever you extracted the SDK zip file, look for the srcextrasexamples folder. Lots of good stuff there. Especially if you’re new to PyS60 and trying to get your head around the way UI works on S60 vs. the way UI works on other platforms, check out the three GUI examples.

I will post in the next couple of days details of the workflow process (including how to set up a bluetooth remote control to execute scripts on a real device), links to some critical documents, and finally the first code from this project.
 
BTW, those who have been following this project from the beginning may wonder what N95 is doing in the title. This blog receives a fair amount of search engine referrals from people looking for ways to hack their devices. Because the N95 is such a hot device right now, it is a popular search keyword. And because what I’m doing for my N93 applies to people interested in their N95, I want to welcome them along for the ride.

Great place. Great people. Stupid story idea.

kevin_s2f | 03 July, 2007 18:25

It’s been a great couple of weeks, but I’m glad to be back. Naresh, Tote and Ron have already commented on the Champion Day. I echo their thoughts that it is wonderful to meet in 3D-land those people who I work with and work for, but rarely actually see.

 

After the Champion Day in Singapore, my partner and I took the train up the Malaysian peninsula to Penang. Everybody I talked to seemed to have the same response: “I hear it’s great – but I’ve never gotten the chance to go.” Well, let me say, they are right about it being great, and they really need to go there some time. It was a fabulous trip. Great food. Interesting people. Places that seem (to my American brain) straight out of a dream. A quite steamy dream, but one worth dreaming at least once in your life. We even had a quite positive encounter with the Malyasian health care system that I’ll share over a good bottle of wine some time.

Star Trek meets Baywatch anyone? 

I had to share this photo with you (taken with my N93, of course). It’s a lifeguard station on the beach outside the resort where I stayed. A great place, but I quite hope American television writers do not take this as a story lead. All we need is a TV series about intergalactic capitalists cavorting in microgravity while their earlobes jiggle in slo-mo.

 

BTW, Ferengi means foreign, or more literally westerner. For the linguistically inclined, here's an interesting trace of the word from the Germanic Frank through the muslim trade routes to South East Asia. And of course the Star Trek reference that came to my mind.

To all I met on the trip, and in particular to those who helped when we needed it, terima kasi!


My Tools for Python on S60 / N93 development

kevin_s2f | 13 June, 2007 01:04

Thanks to Jukka’s tips, during last week’s live session, I think I have my tools decisions made. Here are some are the considerations I brought to the process:
 
I expect and hope to have some cross-platform features, so I want my desktop tools to be as compatible with the mobile runtime as possible. PyS60 is based on Python 2.2.2. Result: I went to the Python download page and located Python 2.2.3. Release notes indicate this is (almost) exclusively a bug fix release, so that works.
I worked with the IDLE tool  that comes with the distribution. Without some help I could only stumble around a bit, but it seems workable. I like that it seems fairly bare-boned – that will help me establish a bit deeper understanding of the guts of the language than if I start right out with a fancy environment that does too much for me. Result: I’ll use Idle to finish my baby step work.
I’m about to head to Singapore for a couple of weeks, so I bought a couple of Python books to keep my occupied on the plane. Turns out the copy of Learning Python   by Lutz and Ascher is based on Python 2.2 – so that’s great.
The last consideration I’ve got is longer term. As I build this out I know I’m going to have C++ extensions involved. I’ve already got an Open C middleware piece I’m contemplating. Result: that means Carbide.c++, probably Express to start because it fits my budget, and the PyDev open source plug-in. 
That’s about it for today. Gotta go pack. Anyone headed to Nokia Connection, Forum Nokia Champion Day, or CommunicAsia, ping me.
1 2  Next»
 
 
Powered by LifeType
     
     RDF Facets:
     
     
     qfnZtypeQUqfnTypeZBlogContentQ
     qfnZtypeQUqfnTypeZCommunityContentQ
     qfnZtypeQUqfnTypeZWebpageQ
     qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX