Here’s my code to display or record two video in one scene. (must be upgrade with glmosaic, by now, you can only use 1 video display on the two screen)

Here’s the return value of my command:GST_DEBUG=GST_BUS:5 ./Gstreamer-3DRendering ‘/home/pierre/Dropbox/demo 05_05_10/VideoMontage/big_buck_bunny.ogg’ FALSE ‘test.ogg’ TRUE TRUE

it gives:
0:00:00.420938212 14582  0x9c1f008 DEBUG                GST_BUS gstbus.c:307:gst_bus_post:<bus1> [msg 0x9e41590] posting on bus, type state-changed, GstMessageState, old-state=(GstState)GST_STATE_READY, new-state=(GstState)GST_STATE_PAUSED, pending-state=(GstState)GST_STATE_VOID_PENDING; from source <gldownload>
0:00:00.420960142 14582  0x9c1f008 DEBUG                GST_BUS gstbus.c:337:gst_bus_post:<bus1> [msg 0x9e41590] pushing on async queue
0:00:00.420972294 14582  0x9c1f008 DEBUG                GST_BUS gstbus.c:342:gst_bus_post:<bus1> [msg 0x9e41590] pushed on async queue
0:00:00.420984307 14582  0x9c1f008 DEBUG                GST_BUS gstbus.c:333:gst_bus_post:<bus0> [msg 0x9e41590] dropped
0:00:00.420995621 14582  0x9c1f008 DEBUG                GST_BUS gstbus.c:333:gst_bus_post:<bus4> [msg 0x9e41590] dropped
Failed to start up pipeline!
0:00:00.421086136 14582  0x9c1f008 ERROR                GST_BUS gstbus.c:838:gst_bus_add_watch_full_unlocked:<bus1> Tried to add new watch while one was already there

(Gstreamer-3DRendering:14582): GStreamer-CRITICAL **: Could not add signal watch to bus bus1
0:00:00.421118123 14582  0x9c1f008 DEBUG                GST_BUS gstbus.c:1056:gst_bus_poll: running mainloop 0xa19d898
0:00:00.421134745 14582  0x9c1f008 DEBUG                GST_BUS gstbus.c:258:gst_bus_set_main_context:<bus1> setting main context to 0x9de7280, GLib default context: 0x9de7280
0:00:00.421154231 14582  0x9c1f008 LOG                  GST_BUS gstbus.c:494:gst_bus_timed_pop_filtered:<bus1> have 34 messages
0:00:00.421248028 14582  0x9c1f008 DEBUG                GST_BUS gstbus.c:498:gst_bus_timed_pop_filtered:<bus1> got message 0x9d50320, state-changed, type mask is 4294967295

gint main (gint argc, gchar *argv[])
{

GstStateChangeReturn ret;
GstElement *videosrc, *decodebin, *ffvideoscale, *glupload, *glfilterreflectedscreen, *glfilterapp, *gldownload, *ffvideoscale2, *theoraenc, *queue, *queue2, *aconverter, *asink, *vorbisenc, *oggmux, *filesink, *glimagesink;

GMainLoop *loop;
GstBus *bus;

// gstreamer initialization
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);

// pipeline’s creation
pipeline = gst_pipeline_new (« pipeline »);

//listen the pipeline bus to get error messages
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, bus_call, loop);
//free the allocated memory for this listening when it isn’t used anymore
gst_object_unref (bus);

//elements creation
//configure the videosource
videosrc = gst_element_factory_make (« filesrc », « source »);
//configure a default source if the user does not specified its own

//configure the decodebin
decodebin = gst_element_factory_make (« decodebin », « decoder »);
//add pads for the audio and video output
g_signal_connect (decodebin, « new-decoded-pad », G_CALLBACK (cb_newpad_video), NULL);
g_signal_connect (decodebin, « new-decoded-pad », G_CALLBACK (cb_newpad_audio), NULL);

//make the rgb mode conversion necessary (it’s compulsory for the glimagesink use)
ffvideoscale = gst_element_factory_make(« ffvideoscale », « videoconverter »);
ffvideoscale2 = gst_element_factory_make(« ffvideoscale », « videoconverter1 »);

queue = gst_element_factory_make(« queue », « queue »);
queue2 = gst_element_factory_make(« queue », « queue1 »);

GstCaps *incaps = gst_caps_new_simple  (« video/x-raw-rgb »,
« width », G_TYPE_INT, 800,
« height », G_TYPE_INT, 600,
NULL) ;

GstCaps *outcaps = gst_caps_new_simple  (« video/x-raw-rgb »,
NULL) ;

//configure the glimagesink
glupload  = gst_element_factory_make (« glupload », « glupload »);
gldownload  = gst_element_factory_make (« gldownload », « gldownload »);
glfilterapp  = gst_element_factory_make (« glfilterapp », « glfilterapp »);
//specifying which function will be used as reshape and draw functions
g_object_set(G_OBJECT(glfilterapp), « client-reshape-callback », reshapeCallback, NULL);
g_object_set(G_OBJECT(glfilterapp), « client-draw-callback », drawCallback_glfilterapp, NULL);

glfilterreflectedscreen  = gst_element_factory_make (« glfilterreflectedscreen », « glfilterreflectedscreen »);
//specifying the options
g_object_set(G_OBJECT(glfilterreflectedscreen), « fovy », 70.0, NULL);

aconverter = gst_element_factory_make (« audioconvert », « aconv »);
asink = gst_element_factory_make (« autoaudiosink », « sink »);

theoraenc = gst_element_factory_make(« theoraenc », « theoraenc »);
g_object_set(G_OBJECT(theoraenc), « sharpness », 2, NULL);
g_object_set(G_OBJECT(theoraenc), « quality », 63, NULL);

g_object_set(G_OBJECT(theoraenc), « keyframe-auto », FALSE, NULL);
vorbisenc = gst_element_factory_make(« vorbisenc », « vorbisenc »);

oggmux = gst_element_factory_make(« oggmux », « oggmux »);

filesink = gst_element_factory_make(« filesink », « filesink »);

glimagesink = gst_element_factory_make(« glimagesink », « glimagesink »);

//test if all object have been created
if (!videosrc || !decodebin || !ffvideoscale || !glupload || !glfilterapp || !glfilterreflectedscreen || !gldownload || !ffvideoscale2 || !theoraenc || !queue || !queue2 || ! aconverter || !glimagesink || !asink || !vorbisenc || !oggmux || !filesink)
{
//if only one failed, the pipeline could’nt work. Error message display
g_print (« one element could not be found \n »);
return -1;
}

//configure the software’s options: the arguments must be:
//1 –> first video source
//2 –> second video source (inactive)
//3 –> output file
//4 –> use display mode
//5 –> use graphics mode
//6 –> use splitted screen

string arg2 = string(argv[2]);
string arg3 = string(argv[3]);
string arg4 = string(argv[4]);
string arg5 = string(argv[5]);

g_object_set(G_OBJECT(videosrc), « location », argv[1], NULL);

if (arg2 == « TRUE »)
display = true;
else if (arg2== « FALSE »)
display = false;

if (!display)
{
g_object_set(G_OBJECT(filesink), « location », argv[3], NULL);
}
else
{
if (arg4 == « FALSE »)
g_object_set(G_OBJECT(glfilterreflectedscreen), « active_graphic_mode », FALSE, NULL);
else if (arg4 == « TRUE »)
g_object_set(G_OBJECT(glfilterreflectedscreen), « active_graphic_mode », TRUE, NULL);

if (arg5 == « FALSE »)
{
g_object_set(G_OBJECT(glfilterreflectedscreen), « separated_screen », FALSE, NULL);
g_object_set(G_OBJECT(glfilterreflectedscreen), « show_floor », TRUE, NULL);
}
if (arg5 == « TRUE »)
{
g_object_set(G_OBJECT(glfilterreflectedscreen), « show_floor », FALSE, NULL);
g_object_set(G_OBJECT(glfilterreflectedscreen), « separated_screen », TRUE, NULL);
}
}

if (display)
{
//adding first element to the main pipeline
gst_bin_add_many (GST_BIN (pipeline), videosrc, decodebin, NULL);
//linking them
gst_element_link (videosrc, decodebin);

//creating video output (with a second bin)
video = gst_bin_new (« videobin »);
//make the association between this pad and the needed format
videopad = gst_element_get_static_pad (ffvideoscale, « sink »);

//ad element to the video bin
gst_bin_add_many (GST_BIN (video), ffvideoscale, glupload, glfilterreflectedscreen, glimagesink, NULL);
//add video bin to main pipeline
gst_bin_add (GST_BIN (pipeline), video);

//verifying that the entry has been converted to rgb format
gboolean link = gst_element_link_filtered (ffvideoscale, glupload, incaps);
//free the memory allocated to the caps
gst_caps_unref(incaps);
if (!link)
{
g_print(« Failed to caps \n »);
return -1;
}

gst_element_link(glupload, glfilterreflectedscreen);
gst_element_link(glfilterreflectedscreen, glimagesink);

gst_element_add_pad (video, gst_ghost_pad_new (« sink », videopad));
gst_object_unref (videopad);

//same action for the audio output (must be tested if there’s no sound)
audio = gst_bin_new (« audiobin »);
aconverter = gst_element_factory_make (« audioconvert », « aconv »);
audiopad = gst_element_get_static_pad (aconverter, « sink »);
asink = gst_element_factory_make (« autoaudiosink », « sink »);

gst_bin_add_many (GST_BIN (audio), aconverter, asink, NULL);

gst_element_link (aconverter, asink);
gst_element_add_pad (audio, gst_ghost_pad_new (« sink », audiopad));
gst_object_unref (audiopad);
gst_bin_add (GST_BIN (pipeline), audio);
}
else
{
//adding first element to the main pipeline
gst_bin_add_many (GST_BIN (pipeline), videosrc, decodebin, oggmux, filesink, NULL);
//linking them
gst_element_link (videosrc, decodebin);

//creating video output (with a second bin)
video = gst_bin_new (« videobin »);
//make the association between this pad and the needed format
videopad = gst_element_get_static_pad (ffvideoscale, « sink »);

//ad element to the video bin
gst_bin_add_many (GST_BIN (video), ffvideoscale, glupload, glfilterapp, gldownload, ffvideoscale2, theoraenc, queue, NULL);

//verifying that the entry has been converted to rgb format
gboolean link = gst_element_link_filtered (ffvideoscale, glupload, incaps);
//free the memory allocated to the caps
gst_caps_unref(incaps);
if (!link)
{
g_print(« Failed to caps \n »);
return -1;
}

gst_element_link(glupload, glfilterapp);
gst_element_link(glfilterapp, gldownload);

link = gst_element_link_filtered(gldownload, ffvideoscale2, outcaps);
if (!link)
{
g_print(« Failed to caps second \n »);
return -1;
}

gst_element_link(ffvideoscale2, theoraenc);
gst_element_link(theoraenc, queue);

gst_element_add_pad (video, gst_ghost_pad_new (« sink », videopad));
gst_object_unref (videopad);
//add video bin to main pipeline
gst_bin_add (GST_BIN (pipeline), video);

//same action for the audio output (must be tested if there’s no sound)
audio = gst_bin_new (« audiobin »);
audiopad = gst_element_get_static_pad (aconverter, « sink »);

gst_bin_add_many (GST_BIN (audio), aconverter, vorbisenc, queue2, NULL);

gst_element_link (aconverter, vorbisenc);
gst_element_link (vorbisenc, queue2);

gst_element_add_pad (audio, gst_ghost_pad_new (« sink », audiopad));
gst_object_unref (audiopad);
gst_bin_add (GST_BIN (pipeline), audio);

gst_element_link(queue, oggmux);
gst_element_link(queue2, oggmux);
gst_element_link (oggmux, filesink);
}

//play the video
//set the pipeline state to PLAYING
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
//display error message if the state cannot be changed
if (ret == GST_STATE_CHANGE_FAILURE)
{
g_print (« Failed to start up pipeline!\n »);
// check if there is an error message with details on the bus
GstMessage* msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
if (msg)
{
GError *err = NULL;
gst_message_parse_error (msg, &err, NULL);
g_print (« ERROR: %s\n », err->message);
g_error_free (err);
gst_message_unref (msg);
}
return -1;
}

// loop for the video playing
g_main_loop_run (loop);

// clean up  when the playing has been done
gst_element_set_state (pipeline, GST_STATE_NULL);
//free all allocated memory
gst_object_unref (pipeline);

return 0;

}

Ces deux derniers jours ont de nouveau été consacrés à la réalisation des vidéos, en collaboration avec Xavier Ladjointe. Après une mise au point avec P.Lochelongue, nous avons convenu de quelques vidéos à modifier et donc, à refaire: le plugin « video surveillance » (4 camera ip sur un écran), le partage de vidéo et les snapshot, et enfin le partage de documents office.

Ceci fait, j’ai ré-encodé chacune de ces vidéos afin que Xavier puissent les travailler et les monter sous window. Pour ce faire, un decodebin associé à un avimux (et un x264enc), et les ogv deviennent des avi. Le pipeline gstreamer est le suivant:

#!/bin/bash

FILE=Whiteboard-Telepointeur

gst-launch –gst-plugin-path=/opt/gstreamer/gstreamer-0.10.25 \
filesrc location=$FILE.ogv ! decodebin name=dec \
dec. ! queue ! ffmpegcolorspace ! x264enc ! \
avimux ! filesink location=$FILE.avi

J’aurais pu l’améliorer en réalisant une liste des fichiers contenus dans le dossier racine et comportant l’extension .ogv, mais certains difficultés, même si elles étaient mineurs, m’auraient pris plus de temps à corriger qu’à encoder en modifiant le nom à la main, donc…

(soit dit en passant, voilà la commande pour récupérer les fichiers susdits:

LISTE=`ls -Rl | grep « .ogv » | cut –delimiter=’.’ -f1` (on récupère tout les noms de fichier comportant .ogv, la partie avant le dit délimiteur)

Finalement, j’ai enfin réussi à mettre en place le pont entre mon formulaire java et mon appli gstreamer, en grattant du côté de l’utilisation de runtime.exec. Il s’agit en fait de ne pas multiplier les appel à exec, mais de n’en faire qu’un seul avec un script comportant toutes les options qui nous intéresse, notamment les exports.

Il me reste donc finalement à comprendre pourquoi le display marche mais plus l’enregistrement…

Il serait temps de poster une petite mise à jour. Afin de montrer que je ne me suis pas tourner les pouces, malgré l’absence de nouveau post.

Les derniers jours ont donc été consacrés à divers points:

Tout d’abord, un magnifique upgrade de Karmic Koala à Lucid Lynx m’a causé pas mal de tort. Alors certes c’est joli ça va plus vite etc mais…tout n’est pas parfait.

Sans entrer dans tout les détails, j’ai déjà évoqué le problème du jdk remplacé par un openjdk, ce qui causait la mort instantanée de mon appli pour le contrôle des caméras ip. Il a donc fallu ajouter diverses petites fonctionnalités dans ce programme afin de s’assurer de son fonctionnement:

-Une détection, juste après l’entré de l’adresse de la caméra, du jdk installé. Pour se faire, on récupère le nom du runtime (la jre) utilisé, et on le subdivise en plusieur string jusqu’à pouvoir comparer le premier mot qui a alors été mis de côté.

-Si c’est openJDK, on lance à l’aide d’un objet runtime l’exécution d’un script qui va permettre l’ajout d’un dépôt dans le fichier sources.list, faire un update des dépôts, installer un jre qui nous convient et forcer la version. Le script est disponible en annexe 1.

-Sinon, on lance execution normalement.

Dans un deuxième temps, nous avons, avec l’aide de Xavier Ladjointe, réalisé les vidéos qui devraient nous permettre de créer les tutoriaux, ou vidéos de présentation, qui seront utilisées pour demontrer les capacités du logiciel UBIK. De nombreuses prises ont été nécessaire (en gros une 50aine) pour ne garder qu’un 15aine de fichiers. Ces fichiers, une fois validés, devront encore être converti en avi pour être monté par Xavier (à moins qu’il ne trouve entre temps un logiciel supportant le ogv sur window, ce qui ne s’annonce pas une partie de plaisir).

Enfin, dans un troisième temps, je me suis approprié le contenu de la nouvelle version du plugin gl de gstreamer via le git de l’équipe de dev. Cela devrait me permettre de me servir de l’objet glmosaic, et ainsi pouvoir remplacer le point noir du second sujet, le montage et la diffusion de vidéos de tutoriaux dans un univers 3D.

On se rappelle que pour le moment, le montage doit être fait en aval, les fonctions opengl de gstreamer ne maîtrisant qu’un seul objet vidéo pouvant être utilisé en tant que texture. Grâce à glmosaic, cela ne sera plus le cas. Après modification, on pourra donc utiliser deux sources vidéos, et ainsi ne plus avoir à faire le dit-montage.

Néanmoins, pour le moment, je suis en passe de réaliser une petite interface graphique beaucoup plus plaisant à utiliser que le remplissage « en dur » dans la console pour les options. Il s’agit ici d’un petit formulaire, ou l’on pourra choisir les deux sources vidéos (une seule d’active pour l’instant) grâce à des browser, et régler les options graphiques à l’aide de bouton radio.

Ces options sont pour l’instant facilement récupérable. Le problème vient du lancement de l’application. En effet, comme, pour l’instant, le contenu de la brique opengl de gstreamer ne suffit pas pour lancer l’appli de visualisateur, il faut tout d’abord spécifier un PLUGIN_PATH, c’est à dire l’endroit sur le disque où se trouve les plugins additionnels dont pourraient avoir besoin les applications gstreamer que l’on va lancer. Néanmoins pour le moment, je ne parviens pas à lancer le programme depuis le formulaire java, pour la bonne raison que cette variable PLUGIN_PATH ne se met pas à jour.

annexe 1: Script de mise à jour du jdk:

#! /bin/bash

if [[ ${USER} != root ]]
then
gksudo « ${0} »
exit
fi

if [[ ${?} == 0 ]]
then
echo « deb http://archive.canonical.com/ lucid partner » >> /etc/apt/sources.list
apt-get update
apt-get install -y sun-6-jdk
sudo update-alternatives –config java
fi

#!/bin/sh

# A simple script to get/compile/install GStreamer

# Nicolas Hennion – GPL

#

# Remarks: the version will be installed in the /opt/gstreamer folder

# Change this to the latest version

GST_CORE=0.10.29

GST_BASE=0.10.29

GST_GOOD=0.10.23

GST_BAD=0.10.19

GST_UGLY=0.10.15

GST_FFMPEG=0.10.10

GST_GL=0.10.1

# Do not edit under this line

sudo aptitude build-dep gstreamer0.10-ffmpeg gstreamer0.10-plugins-bad gstreamer0.10-plugins-bad-multiverse gstreamer0.10-plugins-base gstreamer0.10-plugins-good gstreamer0.10-plugins-ugly gstreamer0.10-plugins-ugly-multiverse gstreamer0.10-plugins-gl

sudo aptitude install bison flex git

if [ ! -e gstreamer-$GST_CORE.tar.gz ]

then

wget http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-$GST_CORE.tar.gz

fi

if [ ! -e gst-plugins-base-$GST_BASE.tar.gz ]

then

wget http://gstreamer.freedesktop.org/src/gst-plugins-base/gst-plugins-base-$GST_BASE.tar.gz

fi

if [ ! -e gst-plugins-good-$GST_GOOD.tar.gz ]

then

wget http://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-$GST_GOOD.tar.gz

fi

if [ ! -e gst-plugins-bad-$GST_BAD.tar.gz ]

then

wget http://gstreamer.freedesktop.org/src/gst-plugins-bad/gst-plugins-bad-$GST_BAD.tar.gz

fi

if [ ! -e gst-plugins-ugly-$GST_UGLY.tar.gz ]

then

wget http://gstreamer.freedesktop.org/src/gst-plugins-ugly/gst-plugins-ugly-$GST_UGLY.tar.gz

fi

if [ ! -e gst-ffmpeg-$GST_FFMPEG.tar.gz ]

then

wget http://gstreamer.freedesktop.org/src/gst-ffmpeg/gst-ffmpeg-$GST_FFMPEG.tar.gz

fi

sudo mkdir /opt/gstreamer

if [ ! -e gstreamer-$GST_CORE ]

then

tar zxvf gstreamer-$GST_CORE.tar.gz

cd gstreamer-$GST_CORE

./configure –prefix=/opt/gstreamer/gstreamer-$GST_CORE

make

sudo make install

cd ..

fi

if [ ! -e gst-plugins-base-$GST_BASE ]

then

tar zxvf gst-plugins-base-$GST_BASE.tar.gz

cd gst-plugins-base-$GST_BASE

PKG_CONFIG_PATH=/opt/gstreamer/gstreamer-$GST_CORE/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig ./configure –prefix=/opt/gstreamer/gstreamer-$GST_CORE

make

sudo make install

cd ..

fi

if [ ! -e gst-plugins-good-$GST_GOOD ]

then

tar zxvf gst-plugins-good-$GST_GOOD.tar.gz

cd gst-plugins-good-$GST_GOOD

PKG_CONFIG_PATH=/opt/gstreamer/gstreamer-$GST_CORE/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig ./configure –prefix=/opt/gstreamer/gstreamer-$GST_CORE

make

sudo make install

cd ..

fi

if [ ! -e gst-plugins-bad-$GST_BAD ]

then

tar zxvf gst-plugins-bad-$GST_BAD.tar.gz

cd gst-plugins-bad-$GST_BAD

PKG_CONFIG_PATH=/opt/gstreamer/gstreamer-$GST_CORE/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig ./configure –prefix=/opt/gstreamer/gstreamer-$GST_CORE

make

sudo make install

cd ..

fi

if [ ! -e gst-plugins-ugly-$GST_UGLY ]

then

tar zxvf gst-plugins-ugly-$GST_UGLY.tar.gz

cd gst-plugins-ugly-$GST_UGLY

PKG_CONFIG_PATH=/opt/gstreamer/gstreamer-$GST_CORE/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig ./configure –prefix=/opt/gstreamer/gstreamer-$GST_CORE

make

sudo make install

cd ..

fi

if [ ! -e gst-ffmpeg-$GST_FFMPEG ]

then

tar zxvf gst-ffmpeg-$GST_FFMPEG.tar.gz

cd gst-ffmpeg-$GST_FFMPEG

PKG_CONFIG_PATH=/opt/gstreamer/gstreamer-$GST_CORE/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig ./configure –prefix=/opt/gstreamer/gstreamer-$GST_CORE

make

sudo make install

cd ..

fi

cd gst-plugins-gl

PKG_CONFIG_PATH=/opt/gstreamer/gstreamer-$GST_CORE/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig ./configure –prefix=/opt/gstreamer/gstreamer-$GST_CORE

make

sudo make install

cd ..

sudo cp /opt/gstreamer/gstreamer-$GST_CORE/lib/gstreamer-$GST_CORE/* /opt/gstreamer/gstreamer-$GST_CORE/lib/

sudo ln -s /opt/gstreamer/gstreamer-$GST_CORE/lib /opt/gstreamer/current

/opt/gstreamer/gstreamer-$GST_CORE/bin/gst-inspect –gst-plugin-path=/opt/gstreamer/current

Aujourd’hui (et les jours derniers), parcours des fonctionnalités de liferay 5.2.3 (je dispose de la version 6.0, mais l’aide est associée à celle-ci, alors, dans le doute et vu que les modifications ne sont pas très très nombreuses…)

Je dispose pour le moment d’un portail sur lequel je gère différentes organizations, locations, communities dans lesquelles sont réparties mes users. A cela s’ajoute la gestion des droits, le parcours des différents portlets existant (l’équivalent des widgets en fait) etc…

C’est un outil relativement simple sur la forme et plus compliqués dans le fond. Une diversification importante est possible au niveau des connexions (via adresse mail directement dans liferay, associé à un serveur LDAP etc). Je ne saisis pas encore tous les fonctionnements (notamment au niveau des croisements d’affichage selon les groupes auxquels appartient un utilisateur donné : on peut en effet compléter la page de base d’un utilisateur en rajoutant des portlets spécifiques à un groupe qu’il rejoint…)

Les portlets sont nombreux: calendrier, blog, message board, partage de doc etc…Tout cela géré par l’administrateur et les équivalents (ceux qui ont les droits d’administration)

En parallèle à cela, je tente tant bien que mal de résoudre les erreurs apparues depuis mon passage sous Lucid Lynx, la version 10.4 LTS de Linux. Comme dit précédemment, openJDK à remplacé JDK. Or certaine fonctionnalité de mon programme sur les caméra PTZ ne fonctionne plus (problème d’accès aux données). Ne pouvant pas réécrire le jdk, je vais devoir me tourner vers une détection de version de java sur la machine exécutrice et proposer une installation d’un jdk « valide » le cas échéant.

De même, l’exécution de mon programme d’écran 3D génère à présent une multitude de warning. Cela n’empêche pas le fonctionnement mais ce n’est pas franchement terrible au niveau apparence. Éventuellement, si je dispose de temps, j’améliorerais la version existante avec une gestion des paramètres par interface, ce qui évitera le panneau de commande et me dispensera de ces warnings (si je ne parviens pas à les supprimer autrement)

Enfin, je dispose dès à présent d’une version du plugin opengl de gstreamer et qui contient le fameux glmosaic, censé pouvoir permettre de préciser deux sources vidéos sans avoir à faire le montage en aval. A nouveau, cela ne compilera pour le moment que sur mon pc, mais l’exécutable devrait marcher sur n’importe quel poste comprenant une version effective de gstreamer. Néanmoins pour le moment, je ne parviens même pas à faire fonctionner l’exemple disponible sur le git utilisant ce fameux glmosaic…En suspend, donc.

Hier et aujourd’hui ont été destiné à l’installation de deux gros logiciels: tout d’abord liferay, afin d’en faire une approche relativement basique avec les exemples qui sont fournis sur le site (7cogs, désinstallation, parcours des options et des widgets etc…)

Mais le gros problème a été d’avoir lancé la mise à jour d’Ubuntu pour Lucid Lynx. Une fois ceci fait (ce qui a déjà pris une demi journée, mine de rien), je ne peux plus lancer mon logiciel de contrôle de caméra ip à distance.

Pour être tout à fait exact, le logiciel se lance comme il faut. Les envois de requêtes sont fait comme il faut, les traitements aussi (à en juger par les déplacements de la caméra sur le bureau en face), mais le streaming ne fonctionne plus. il semblerait que le projet, lorsqu’il fut bâti sur Karmic Koala, reposait sur le JDK-6 de sun. Dans le Lucid Lynx, ubuntu à remplacer ce paquet java par l’openJDK-6. Ce devrait être strictement la même chose, mais désormais les codes inclus dans le code de java sont en accord avec la licence GPL, afin d’assurer une portabilité supérieure.

Oui mais non. Le streaming ne fonctionne plus, comme je l’ai dit, et il semblerait que le problème soit lié à cette modification. J’ai donc, après une demi journée de recherche, fini par remplacer le lien symbolique entre eclipse et l’openjdk par un lien vers un jdk-6 fonctionnel que j’ai téléchargé sur le site de sun. Malheureusement, cela ne fonctionne toujours pas, et je commence à être à court d’idée sur comment faire.

Pour finir ma journée, j’ai réaliser un .jar, un fichier exécutable sur ubuntu et exportable sur une autre machine. En faisant ainsi, je peux lancer le projet sur un autre pc (mon second post, toujours sur karmic koala) et voir que le streaming fonctionne. il semble donc correct de dire que le problème vient bel et bien de Lucid Lynx…A tenter de corriger donc.

Hier et aujourd’hui ont été consacré à la résolution du problème qui me coinçait depuis maintenant une semaine: la récupération des presets de la caméra ip.

jusqu’alors, j’avais cherché à analyser une fonction javascript travaillant sur le dom de la page html chargée, côté client donc, et ne parvenait pas à trouver un moyen de dire à mon application de récupérer les valeurs.

Ma nouvelle approche a finalement simplifié le problème. Il existe en effet, une fois la page CHARGEE, une ligne de code html qui regroupe les noms des preset enregistrés. Plus besoin donc de les récupérer dans le DOM, puisqu’on peut récupérer directement la ligne html et la traiter. Je n’avais de prime abord pas trouvé cette ligne à cause d’une recherche via ctrl+f avec les mots clés PTZ ou preset.

Bref la ligne à partir de laquelle je travaille est désormais de la forme:

<input type="hidden" name="root_PTZ_PresetPos_P0_Pos" value="home~server:1:-2147471303:1:1:-12.2634:1.2261:2998:7663:4058:false" >
<input type="hidden" name="root_PTZ_PresetPos_P0_Label" value="home" >

Le travail se découpe alors en ces quelques sous parties:

1- requête GET pour obtenir le code complet de la page html

2- dans la réponse reçue par l’appli, trouver la ligne précédant la-dite ligne

3-stocker la ligne recherchée

4-la découper et redécouper selon les caractères « <« , ne garder qu’une string sur deux (on ne s’occupe pas de la première ligne car plus difficile à traiter), « = » et  »  » « . On obtient alors une liste de chaîne, stockée dans un ArrayList, regroupant les nom des différents preset.

Une fois ces noms trouvés, je désirais les afficher dans une combobox pour permettre à l’utilisateur de les sélectionner sans avoir à connaître nécessairement les différents nom ou id des presets de sa caméra (caméra prêtée, caméra commune sur le lieu de travail etc). Le problème venait de la connexion requise par certains serveur de caméra. Ne pouvant pas mettre en place une détection directe au lancement du programme, j’ai opté pour un bouton qui, une fois cliqué, lance la fonction de récupération des preset, et une fois ceux ci stockés, laisse la place à la combo box.

Il a ensuite fallu gérer les réactions du programme. En effet, chaque ajout ou suppression de preset, comme ils sont autorisés, nécessite de remettre à jour la liste. Il faut donc effectuer à nouveau la détection, sans toutefois nécessairement déplacer la caméra. En effet, l’ajout d’un nouveau preset par exemple se fait comme suit:

1-clique sur le bouton ajout

2-entré du nom

3-ajout de ce preset sur le server de la caméra

4-Mise à jour de la liste

5-réaffichage

Or, la récupération de la liste, telle que faite à la base, déclenchait automatiquement un déplacement vers le premier item de la liste, ce qui donnait une impression de saute d’image (on allait au premier endroit et on revenait au nouveau en très peu de temps). Il a donc fallu inclure une gestion de booléen pour déterminer si on doit oui ou non se déplacer. Une fois ceci fait, le logiciel est terminé. Son aspect général est alors:

Et une fois les presets chargés (je n’arrive pas à screener avec la combobox déroulée…étrange)

Aujourd’hui suite du travail sur le récupération des preset caméra. L’évaluation de fonctions javascript est à présent possible par deux biais:

le JRE (framework java) incorpore depuis la version 6.0 une version de Rhino qui permet de manipuler directement ces fonctionnalités. Néanmoins Rhino ne supporte pas Window et document, deux fonctions souvent utilisées dans les fontions js.

Il existe de plus dans les jar associé au JRE une archive intitulé plugin.jar. Celle-ci regroupe les fonctionnalités de l’ancien package netscape.javascript, des méthodes de connexion et d’utilisation des fonctions js d’une page html dans une applet et vice versa. Néanmoins, je ne désire pas utiliser des fonctions js qui vont modifier la page html. Je dois donc trouver un moyen (s’il existe, et je commence à sérieusement désespérer) de récupérer la page html qui m’intéresse, récupérer les infos de son DOM et interagir avec. Depuis une semaine que je travaille là-dessus, c’est ce que j’ai réussi à faire de plus avancer. Néanmoins, il ne m’est toujours pas possible de travailler directement avec ce DOM, et je n’ai pas la moindre idée de comment faire. Les post sur les différents topics d’aide, si utile jusque là, se révèlent à présent inutile et personne ne semble être en mesure de m’aider sur ce problème…

Aujourd’hui poursuite sur le travail des derniers points noirs du logiciel:

Le problème des textes non centrés sur les boutons est finalement réglé! Après avoir tenté maintes et maintes fois diverses méthodes pour centrer le bouton à sa création, je me suis rendu compte qu’il existait une méthode écrite dans le code (d’où l’utilité des commentaires, qui étaient entièrement absents dans le code d’origine), qui gérait l’aspect graphique des boutons: le fond ET le texte. Les modifications dans le constructeur était alors annulées par cette méthode qui plaçait le texte de manière relative: ça fonctionne si le texte n’est pas trop grand. on fait, on plaçait le texte un peu avant le milieu du bouton:

calcul des x: this.getWidth() / 2 – this.getWidth()/2/4.

Vu que les tailles sont fixes, on ne prenait pas vraiment en compte la taille du texte. J’ai donc modifié ceci en:

this.getWidth() / 2 – this.getText().length() * 7;

Cette fois, le texte reste « au milieu » quelque soit sa taille.

Le deuxième problème était l’obtention de la liste des preset de la caméra.

Pour se faire, je récupère le code html de la page qui les regroupe (sequence mode dans la page des setup) et traite le résultat. Mais la valeur retournée est en javascript. je cherche donc un moyen d’intégrer du javascript dans une appli java. Le problème est que l’inverse se fait beaucoup, mais pas dans ce sens là.

J’ai néanmoins fini par dénicher quelques pistes:

Rhino, transcripteur de javascript écrit en java. Mais la documentation n’est pas très efficace, et le projet semble être un peu à l’abandon (associé au JDK 1.6…)

JSObject, qui devrait permettre de travailler sur le DOM d’une applet. je cherche à savoir s’il est possible de travailler directement sur le DOM d’une page HTML

DOMService, même chose que JSObject.

Les recherches sont longues et visiblement très peu utilisée (les deux derniers sont des packages non inclus dans le JDK de sun par exemple).

Aujourd’hui, journée consacrée aux derniers points qui restent insolubles:

J’ai cherché à obtenir d’une manière ou d’une autre les différents presets sauvegardés sur la caméra ip. Pour se faire, j’ai cherché à passer via une requête HTTP, comme pour le reste des contrôles, mais cette fois une requête GET, puisque le contenu de la page ne doit pas être modifiés. Connaissant la page de setup de la caméra axis, il suffisait (si tout allait bien dans le meilleur des mondes) de demander cette page via GET, et de traiter les donner (le retour est un code de page html).

Néanmoins, deux problèmes se posent: le premier est que la page demandée est en shtml. Je ne sais pas concrètement si httpURLConnection supporte ce format. En effet, la page d’accueil du live view, en http/html, est bien renvoyé si la requête porte directement sur elle. Mais pas la page de configuration.

De toute les façons, après avoir utiliser un sniffer de requête (ce qui m’a permis de connaître le type de requête envoyé à l’ouverture de la page dans un browser) et contrôler le code source de la page demandé, je me suis rendu compte que le contenu de celle-ci était en javascript. De là, l’applet ne semble pas gérer le javascript, premier problème qui devrait pouvoir être contourné, mais il faudra alors « dé-compiler » le code source et le réappliquer si c’est possible. Bref, si cela reste visiblement (et encore, pas sûr) envisageable, la partie s’annonce très très dure.

Le second problème reste le fait que le texte de mes boutons refuse de se centrer. J’ai tenté diverses approches: travailler sur le texte directement, incorporer des labels sur les boutons et gérer leur tailles, puis celle des boutons, resize général etc…rien ne marche.

Dans le cadre des Up/Left/Down/Right, le problème n’est pas très grave, mais pour les Goto, Del et Save Preset, seule la moitié gauche du texte est visible, et ce n’est pas franchement correct.

Bref une journée longue sans grand résultat.