Saturday, January 2, 2010

From m4a to mp3 !

From time to time, I use animoto to generate short videos. I like to use my iTunes music as sound track but always face conversion problems. iTunes stores the songs in an m4a format while animoto uses mp3 only.
After a while, I figure out a simple way to convert files from a format to an other. For this I used faad (an open source MPEG-4 and MPEG-2 AAC decoder) and lame the well known mp3 encoder.
Both install nicely on Mac OS.
A typical transcoding sequence is as follows:

faad -o sample.wav sample.m4a

lame -h -V 6 sample.wav sample.mp3

... but you might find additional and more useful combination reading the help.

Happy transcoding

Saturday, August 15, 2009

Pop passe a la maison

Vous ne connaissez sûrement pas Pop, alors laissez moi vous le présenter rapidement. Pop est la marionnette dont j'ai entendu parle toute l'année mais que, finalement, j'ai vu assez peu. Je suppose que tous les maris d'instit connaisse cette situation :) Je peux affirmer sans trop me tromper que Pop était (ou est peut-être encore qui sais) un support pédagogique, une espèce d'entremetteur entre la maîtresse et les enfants (ça doit être moins intimidant de parler à un dragon qu'a la maîtresse) ...

Voila donc que vers la fin de l'année, Pop qui couchait, jusqu'alors, sagement a l'école se met a faire plus de "sleep over" que je n'ai pu en faire dans toute ma jeunesse. Pris d'une soudaine crise de jalousie, je confie à la maîtresse une invitation pour Pop, l'enjoignant de considérer Horizon Green comme un lieu possible de villégiature. Eh bien vous savez quoi, Pop est venu à la maison ... et j'ai respecté attentivement les consignes suivantes:
  • lui apprendre quelquechose
  • lui raconter une histoire avant de se coucher
  • lui faire se brosser les dents
  • lui faire un super lit (désolé la photo est censurée par la maîtresse)
Je n'ai pas pu écrire dans le carnet de voyage :'( - la maîtresse l'a interdit.
Vous ne me croyez pas ... les photos sont ici.

Bonne continuation Pop ...

Tuesday, April 21, 2009

Transfering a video to your iPod

Did you ever try to copy localy a YouTube video that seemed interesting to you ? It happened to me few days ago. On my Mac, I solved the problem by looking in the /var/folders directory where temp copies are hold.
In order to locate more precisely I had to do the following:


touch /tmp/now

find /var/folders -newer /tmp/now -print

while the video is still loading.


Then it is just a matter of converting the flash format to the m4v format, Handbrake will do the job for you.

Friday, February 20, 2009

Ogame c'est fini ... pour le moment

Juste pour la petite histoire, ce matin j'ai arrêté ogame a une petite vingt-cinquieme placeUn grand merci a Isildur, Amy et Percy !
Bonne continuation a tous les gamers fous qu'ils soient Moches ou pas - et en particulier a MN :) mais aussi tous les anciens LEM - surtout Uru mon bon fournisseur en deut, Jocker et ses Mouhahaha retentissants et Arca et son fameux gateau au chocolat ...
Angeluis fais attention a ma caravane, je reviendrais peut-etre !
Je remercie enfin le clochard qui m'a permis de reprendre mon tag ...

Wednesday, August 13, 2008

Real programmer don't eat much quiche (Part I)

I don't know much about Glen and Peter. I am just a fan of Gravl and a reader of Glen's blog but I am sure that their book "Grails in Action" will be a blockbuster in the community.
So feel free to buy the book, the TOC is quite appealing and I am sure that we will get plenty of practical examples.

Tuesday, August 12, 2008

My Wordle

Sunday, August 10, 2008

Street soccer (part I)

Remi Gaillard is a French actor who has set up his own web TV. His well known for one video done for Nike in a kind of street soccer precision shoots.
Here are two of his short movies:








If you wan to see more videos, go directly on his web site.

Saturday, June 21, 2008

YUI Treeview & Grails

In a project I need a kind of CMS in order to store/retrieve large files. Basically my choices were narrowed down to Alfresco and Grails.
Alfresco was seen as the "low entry cost" solution, Grails requiring more work but being more flexible.
Obviously my main requirement was to be able to upload large files (>10 GB). Obviously this can not be done using the browser and a specific (but simple) client had to be designed. Testing this with Grails took me one day, many tutorials being available [1][2]. With Alfresco despite many post to the forum, I am still stuck to the 2GB limit ...

I decided to go on with Grails. My next step was to be able to visualize the data being stored on the server. For this I decided to use the YUI Treeview component. Here is the controller I used:


// show.gsp will be used
def show = {
}

def dir = {
def cmsId = params.cms
def dir = params.dir?:"/"

// Removing some characters from the path
dir = dir.replaceAll("\\.\\./","")

// Get the root dir for the CMS
String configDir = grailsApplication.config.cmsdata.dir

String target = configDir + cmsId + dir

def files = []
File d = new File(target)
if (d.exists() && d.isDirectory()){
files = d.listFiles()
}

// return back a JSON structure
response.setHeader("Cache-Control", "no-store")
render(contentType: "text/json") {
nodes {
for (f in files) {
node(name: f.name, isDir: f.isDirectory())
}
}
}
}


The view is really simple. When you click on a tree node, the path is constructed the controller is called, the JSON is parsed and new tree nodes are created dynamically differentiating leaf nodes. (Here is the jscript part).




(function(){

// Creating the tree
function buildTree() {
var tree;
tree = new YAHOO.widget.TreeView("treeDiv");

tree.setDynamicLoad(loadNodeData);

var root = tree.getRoot();

var tempNode = new YAHOO.widget.TextNode("/", root, false);

tree.draw();
}

// Processing new nodes
function loadNodeData(node, fnLoadComplete) {
var path = "";
var leafNode = node;
while (!leafNode.isRoot()) {
path = leafNode.label + "/" + path;
leafNode = leafNode.parent;
}

var nodelabel = encodeURI(path);

var sUrl = "${params.cms}/dir?dir="+nodelabel;

var callback = {
success: function(oResponse){
var oResults = YAHOO.lang.JSON.parse(oResponse.responseText);

if ((oResults.nodes)&&(oResults.nodes.length)){
if (YAHOO.lang.isArray(oResults.nodes)) {
for (var i=0; i < oResults.nodes.length; i++){
var tempNode = new YAHOO.widget.TextNode(oResults.nodes[i].name, node, false);
tempNode.isLeaf = !oResults.nodes[i].isDir;
}
}
}
oResponse.argument.fnLoadComplete();
},
failure: function(oResponse){
oResponse.argument.fnLoadComplete();
},
argument:{
"node": node,
"fnLoadComplete":fnLoadComplete
},
timeout:5000
}

YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
};

YAHOO.util.Event.onDOMReady(buildTree);
}());



If you want to work offline (as I did), you have to install the excellent YUI Plugin.

The next step for me is to package this in a YUI panel :)

Saturday, May 3, 2008

Groovy 1.6-beta-1: c'est de la bombe :-)


>groovy -v
Groovy Version: 1.5.6 JVM: 1.5.0_13-119
>date; groovy Mandelbrot.groovy ; date
Sat May 3 22:03:53 SGT 2008
Groovy Elapsed 25.721
Groovy Elapsed 24.552
Groovy Elapsed 26.606
Sat May 3 22:05:12 SGT 2008


>/Applications/groovy-1.6-beta-1/bin/groovy -v
Groovy Version: 1.6-beta-1 JVM: 1.5.0_13
>date; /Applications/groovy-1.6-beta-1/bin/groovy Mandelbrot.groovy; date
Sat May 3 22:31:16 SGT 2008
Groovy Elapsed 5.198
Groovy Elapsed 5.174
Groovy Elapsed 5.273
Sat May 3 22:31:32 SGT 2008


x5 !
Congrats to the team !

Friday, May 2, 2008

Groovy and Twitter (Part 1)

Looks like Twitter will be under the spotlight at JavaOne this year. Posts on this topic are popping everywhere. I already talked about the "Script Bowl" session but if you are attending JavaOne you should probably have a look to this post.

But back to Groovy, I propose to write a simple class to interface to Twitter and then build mashup. But first, let's draft some specs. All communication with the server goes through http and sticks to the REST approach. You can find most of what I used here and there. Before going further, you must be familiar with some of the Twitter's terminology:
  • Tweet
    Every person has a status. Updating the status with a new one is the same as sending a tweet. Tweets have to be smaller than 140 characters.
  • Friends
    people you are subscribed to (following)
  • Followers
    people who are subscribed to your tweets
Some other concepts are:
  • Direct message
    a private message sent between two (or more) users.
  • Replies
    you can reply to another users’ tweets using the @username prefix in your own tweets.
In order to start, I would like my class to be able to:
  • authenticate to the server using a given login (and associated password)
  • retrieve the friends of that user
  • update it's status
So let's go ...

1. Authentication. This is fairly easy since Twitter uses Basic Authentication. I propose to set an authenticator using a Groovy syntax ;-)

Authenticator.setDefault(
[getPasswordAuthentication : { return new PasswordAuthentication(name, password as char[]) } ] as Authenticator
)


2.Retrieve friends. Fairly easy as well, we just need to send a GET request to http://twitter.com/statuses/friends/${user.id}.xml and yes you have to add ?page=$page if you have plenty of them. In this request, user is a Twitter user returned by getUser().
3.Update your status. Last by not least, we need to update our status. This is done by sending a POST request to http://twitter.com/statuses/update.xml using a RESTful request.

An example is worth thousands of words:

twitter = new Twitter("guillaume.alleon@gmail.com", "****")
twitter.postUpdate("Finalizing my Groovy Twitter API")

def u = twitter.getUser("glaforge")
println "Id of Groovy grand master is ${u.id}"

def f = twitter.friends
f.each{println it.name}


Obviously this API is still in its infancy, I have been playing with it few hours. You will be able to get it here: http://code.google.com/p/groovy-twitter/

Thursday, May 1, 2008

Still alive ...

Well you could wonder if this blog is still alive ... Alas it has not been very active these last few months but I will try to resurrect it a bit. A lot has happen recently:
  • Apache CXF has graduated,
  • G2One and the Groovy team have released version 1.5.6
  • Gradle has been out
It then time for a new version of GroovyWS !

JavaOne 08 is next week. "Au Menu" will be a "Script Bowl" session. I will try to post some examples on the proposed apps (twitter & the world web app) before the conference starts (as I am sure you will get better solution there ;-))

So see you soon !

Saturday, January 5, 2008

Using GroovyWS with the TerraService (Part 1)

I got recently a post on the difficulty of retrieving complex elements by some webservices, I will try to clarify some issues on this in this post using the Microsoft Terra webservice.
The TerraService is an WebService API which allows you to query the Microsoft TerraServer database of high resolution aerial imagery. Among other things, you can:
  • Find Geographic and Image Coordinates by Place Name
  • Convert coordinates from one projection system to another
  • Fetch tile meta-data and image-data
Today, I will just concentrate on using the search API to show how to deal with arrays with GroovyWS.

If you look at the TerraService WSDL you will notice that some functions return arrays. This is clear from the following part of the WSDL:


<s:element name="GetPlaceList">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="placeName" type="s:string"/>
<s:element minOccurs="1" maxOccurs="1" name="MaxItems" type="s:int"/>
<s:element minOccurs="1" maxOccurs="1" name="imagePresence" type="s:boolean"/>
</s:sequence>
</s:complexType>
</s:element>

<s:element name="GetPlaceListResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="GetPlaceListResult" type="tns:ArrayOfPlaceFacts"/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="ArrayOfPlaceFacts">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="PlaceFacts" type="tns:PlaceFacts"/>
</s:sequence>
</s:complexType>

<wsdl:message name="GetPlaceListSoapIn">
<wsdl:part name="parameters" element="tns:GetPlaceList"/>
</wsdl:message>
<wsdl:message name="GetPlaceListSoapOut">
<wsdl:part name="parameters" element="tns:GetPlaceListResponse"/>
</wsdl:message>

<wsdl:operation name="GetPlaceList">
<wsdl:input message="tns:GetPlaceListSoapIn"/>
<wsdl:output message="tns:GetPlaceListSoapOut">
</wsdl:operation>

Therefore, the following call to GetPlaceList will return an object embedding an array of PlaceFacts.

def proxy = new WSClient("http://terraservice.net/TerraService.asmx?WSDL", this.class.classLoader)
def plist = proxy.GetPlaceList("mountain view", 5, true)

From this object, one can call getPlaceFacts to get the array. Here we asked for its size:

println plist.placeFacts.size()

Then one call go through all the places returned by the call to the TerraService:

for (pfact in plist.placeFacts) {
println pfact.place.city
println pfact.place.state
}

All this might look a bit cryptic, and it is probably. The fact is that there is no magic. When you want to call a remote service, you have to know its signature. If you don't have any manual then you have to read and understand the WSDL which represents the contract you are offered.

If you have any idea on how thing could be improved by GroovyWS for helping you in writing your scripts then do not hesitate to give your feedback.

Tuesday, January 1, 2008

Happy new year - Bonne année 2008

Quelques petites nouvelles de début d'année: 2007 s'est finie pour nous par un séjour de quelques jours à Malacca (Malaisie). Nul doute que soph postera prochainement une description plus complète de nos visites. J'en profite pour vous souhaitez une très bonne année 2008; quelle vous apporte surtout la santé (le reste suivra, j'en suis sûr).

Dans le chapître des bonnes résolutions (car point de nouvelle année sans de nouveaux objectifs), je vous dirais bien que j'essayerai d'être plus présent sur ces pages, que je prendrai plus de vacances, que je ferai le marathon de Singapour, .... M'enfin n'y croyez pas trop !

A toutes fins utiles, et pour ceux qui voudraient se joindre à moi, le marathon de Singapour aura lieu cette année le 7 décembre.

Sur ces bonnes résolutions, je vous laisse et n'hésitez pas à me communiquer vos bonnes résolutions en commentaires.

Sunday, December 16, 2007

GroowyWS 0.2.0

It has been a long time since I talked about GroovyWS ... Groovy has been out for a week now and I have been working a bit on GroovyWS as well so I decided to push a new version. The changes brought by this new version are minor in term of workload but they should (hopefully) made GroovyWS more usuable in a production environment.
The first change deals with https support. Now you cab use the WSClient with a serving using secure http. This has been tested using Amazon S3 web services:

def proxy = new WSClient("https://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl",..)

You can now create buckets :-)

The other major change is the support for servers using basic authentication. So if your server requests to have an "Authorization: Basic bG9naW46cGFzc3dk" header in the request, you are able to set the correct properties using:

System.props["http.user"] = "login"
System.props["http.password"] = "passwd"

Do not forget that the token transmitted is just a base64 encoding of "login:passwd", so basically your are transmitting your credentials in clear text :-). You don't trust me ? Try this:

echo -n 'login:passwd' | openssl enc -a -e

or

echo 'bG9naW46cGFzc3dk' | openssl enc -a -d

Only use this over https !

The last minor change is to publish the SOAPAction property in the WSDL generated by the server. This makes odd commercial products work with WSServer !

What are the next steps ? I would like to add WS-Security support. This is something I already have partially, I am missing a public server to test it and would like to know how you would envisage its usage using groovy. So if you have any idea, do not hesitate to contact me ...

Sunday, August 26, 2007

GroovySOAP is now GroovyWS

It has been a long time without news. The fact is that I have been moving from France to Singapore and that keeps me busy with and away from the keyboard. Anyway I am back. You probably now that CXF has taken over XFire. Thanks to the work done by Dan & Al, the move has been pretty fast and we now have the best from XFire & Celtix.
I thought it was time to move also from GroovySOAP (relying on XFire) to GroovyWS (build on top of CXF). What are the difference so far ? If you choose GroovyWS you will have to use Java5 but you will gain an easiest way to build your clients (no worries about the complex types, they are automatically generated) and a proxy support.
In the future, I will probably start to work on basic authentication as this has been asked several times.
The build can be found here.

Friday, August 24, 2007

Songs of the sea

Hier, soir nous avons passé la soirée à Sentosa accompagné de Jean-Yves et David. On peut accèder à cette île (destinée uniquement aux loisirs) par différents moyens. Cette fois-ci, David avait choisi les oeufs (oui vous avez bien lu) afin de nous faire profiter de la vue sur la ville. Au programme: "Songs of the Sea" un spectacle réellement féérique fait de feux (follets) et de jeux de lumières et de lasers projetés sur des jets d'eaux. Le spectacle raconte l'histoire de Li - jeune homme doté d'une voix charmeuse. Li et ses amis découvrent l'existence de la princesse Ami sous l'emprise d'un village enchanté. Réussiront-ils à la délivrer avec l'aide des créatures de la mer ?

Bon allez, si vous voulez la réponse il vous faudra venir découvrir le spectacle ... Bon, au pire nous vous avons mis quelques photos ici.

Sunday, August 19, 2007

Visite au zoo

Première semaine à Singapour ! Après avoir tenté d'évaluer les différents moyens pour aller de notre nouveau domicile au boulot (1h15 ;-) ), le premier week-end nous a permis de souffler un peu. Samedi, ce fut direction le centre ville afin de rendre visite au Merlion (emblème de Singapour) situé en bord de mer, puis de faire du shopping chez Carrefour: nostalgie oblige. Dimanche, direction le zoo à une trentaine de minutes de chez nous (bus 138 !), on en a pris plein les yeux avec des animaux inconnus chez nous (par exemple les tragulidés - oui je sais ils ne sont pas particulièrement beaux !). Aux programmes: perroquets colorés, caméléon, singes en tout genre, lémuriens, éléphants et de nombreux autres que je vous invite à découvrir ici . Nous avons même pu découvrir quelques serpents fort peu recommendables qui trainent par ici.

A bientôt, pour de nouvelles aventures.
Posted by Picasa

Wednesday, May 9, 2007

Embedding Google Maps in your Groovy application

Google provides a wide variety of API for embedding their applications into your web pages. They are very convenient if your are developing web applications but I find it very painful to embed them into any Java application. Hopefully as far as GMaps is considered, the swingx-ws project is providing a JXMapViewer class in which you can configure a tile provider for using the Google map servers. Let's use Groovy to build a small apps using Google geocoding and putting some information on a map.

Central to our small application is the JXMapViewer. Each mapviewer is associated to a tile factory which delivers the image pieces. Once configured, the mapviewer will take care of the rest querying the map server when required depending on your location. Configuring the tile factory is the more tricky part of the snipplet, here are all the arguments of the constructor:

def tfi = new TileFactoryInfo(0, 20, 17, 256, true, true,"can't disclose", "x", "y", "zoom")

The first four numbers to the TileFactoryInfo constructor represent the minimum zoom, the maximum zoom, the total zoom levels, and the tile size (very often a tile is a 256 pixels square) . The two booleans are used to indicate if the x coordinates go left to right or right to left and if the y coordinate goes from top to bottom or out from the equator. The rest of the parameters are for the base url and the name of the http parameters in the get request to fetch tiles.

Let's continue by defining our Swing interface including the JXMapViewer. Here the code defining our panel which includes a textfield (in which you could type an address), the widget containing the map viewer and two buttons for zooming in and out.


import java.awt.*
import java.awt.BorderLayout as BL

import javax.swing.*
import javax.swing.WindowConstants as WC
import javax.swing.JOptionPane as JOP
import javax.swing.BorderFactory as BF
import javax.swing.SwingUtilities as SU

import org.jdesktop.swingx.mapviewer.*
import org.jdesktop.swingx.JXMapViewer

import groovy.swing.SwingBuilder

def googleKey = "your google api key"

def mapViewer = new JXMapViewer()
def tfi = new TileFactoryInfo(...)

mapViewer.tileFactory = new DefaultTileFactory(tfi)
mapViewer.zoom = 5
mapViewer.centerPosition = [48.856558, 2.350966] // Paris

def swing = new SwingBuilder()
def frame = swing.frame(title: 'Groovy Maps',defaultCloseOperation:WC.DISPOSE_ON_CLOSE) {
panel(id: "mainPanel", layout: new BL()) {
panel(constraints: BL.NORTH, layout: new BL()) {
textField(id: "address", constraints: BL.CENTER, columns: 50,
border: BF.createTitledBorder("Address"), actionPerformed: {
def address = swing.address.text
// geocoding code here
}
widget(mapViewer)
panel(constraints: BL.SOUTH) {
button(text: "+", actionPerformed: { mapViewer.zoom -= 1 })
button(text: "-", actionPerformed: { mapViewer.zoom += 1 })
}
}
}
frame.pack()
frame.size = [800, 600]
frame.locationRelativeTo = null

frame.visible = true



Using the Google geocoder is pretty simple when using an http request to http://maps.google.com/maps/geo? with the following parameters in the URI:
# q, the address that you want to geocode,
# key, you API key,
# output , the format in which the output should be generated. In our example, we will use xml, the other options are kml, csv, or json.

In our case, the address will come from a texfield so the code looks like this:

textField(id: "address", constraints: BL.CENTER, columns: 50,
border: BF.createTitledBorder("Address"), actionPerformed: {
def address = swing.address.text

// geocoding
SU.invokeLater {
Thread.start {
def geocodingUrl = "http://maps.google.com/maps/geo?q=
{URLEncoder.encode(address)}&output=xml&key=${googleKey}".toURL()
def node = new XmlSlurper().parseText(geocodingUrl.text)
if (node.Response.Status.code == "200") {
def coord = node.Response.Placemark.Point.coordinates.text().
tokenize(',').collect{Float.parseFloat(it) }
mapViewer.centerPosition = coord[1..0]
}
}
}
})


Assemby all the pieces give you the global application ...

In conclusion, JXMapViewer is a powerful component that make it easy to embed maps in your groovy application. In a next stage, I will show you how to add more information in a different layer.

Wednesday, May 2, 2007

J-7 for JavaOne 07

Now that Groovy-1.1-BETA-1 and Grails-0.5 are out, it's time to focus on JavaOne. There will be an important presence for both projects since at least 8 sessions are mentioning Groovy. Apart from these sessions, two other events are worth to attend:
# On May 7, if you are in SF and are interested by dynamic languages - don't miss the RedMonk unconference track during the CommunityOne event,
# On May 8, join the Groovy and Grails community for the Groovy/Grails One Meet-up at the W Hotel from 6:30pm.

And probably many more to be announced !

Groovy is enterprise ready

It has been a long time since my last post. But important things are happening for enterprise scripting. Yes, Groovy-1.1-beta-1 was released yesterday. This release has new features that could speed up its adoption at the enterprise level. In this post, let's focus on annotations that is something brought by Java 5. Nowadays, annotations are everywhere from Spring Framework, Hibernate, TestNG to the newcomer Google-Guice lightweight dependency injection framework.
Let's see how Guice and Groovy can be used jointly.
All you need is a fresh Groovy 1.1-beta-1 install and guice-1.0.jar and aopalliance-1.0.jar from Google-Guice. As an example, I will use the stupid mathematic application I am using for the GroovySOAP tutorial.
Let say, you have an addition contract like this one:

import com.google.inject.*
interface Calculator {
def add(a,b)
}

Here is an obvious instanciation of that contract (this should be implemented as a singleton):

@Singleton
class CalculatorImpl implements Calculator {
def add(a, b) {a + b }
}

The next step is to write the client that will need that service to be injected. In Groovy, this is as simple as shown below. The @Inject annotation is used for that purpose.

class Client {
@Inject
Calculator calc

def executeCalc(a, b) { calc.add(a,b) }
}

What is not yet done is the wiring between our client and the implementation class. This can be done programmatically using the so called Modules in Guice. Here is what I am doing here:

class MyModule implements Module {
void configure(Binder binder) {
binder.bind(Calculator).to(CalculatorImpl)
}
}

At this point, we are done. Here is how you can use your client in Groovy:

def injector = Guice.createInjector(new MyModule())
def client = injector.getInstance(Client)
assert 3 == client.executeCalc(1,2)

If you want to learn more on this topic, here are further reading on Guicy by MrG and some early experiment on JPA and annotations in Groovy by Romain.