ImageViewer pour MacOSX

Juste un petit post pour signaler la mise à jour de mon image viewer. Cette version est une refonte du code source, destinée à corriger tous les bugs, problèmes de performances et petits problèmes liés à quelques choix d’implémentation “naïfs”.

Cette version est extrêmement simpliste : pas de fullscreen, pas de slideshow, aucune option. Par contre, la navigation des répertoire est désormais parfaitement fluide, il n’y a plus de fuite mémoire, et surtout, plus aucun bug avec la lecture des gifs animés !

Et bien évidemment, un code source un peu mieux structuré, beaucoup moins de dépendances entre les différentes parties de l’application, ce qui devrait faciliter l’intégration des anciennes options, et éventuellement de nouvelles.

Pour finir, la page est ici : http://blog.pcitron.fr/tools/macosx-imageviewer/ Et à partir de cette version, l’application précompilée est inclue (compilé sous Lion, donc Intel seulement)

Mont Tremblant

Petit post pour raconter ma vie et un WE de trois jours très sympa :) Le WE dernier donc, lundi férié (la fête de la reine) et donc petit WE loin du béton Montréalais, à Mont Tremblant. Petite note sur les jours fériés ici : la plupart sont placé au Nième lundi ou vendredi du mois ! En gros, ici quelque soit l’année et quelque soit le jour férié, ça fait un WE de trois jours assuré :)

Bref. Le mont Tremblant pour ceux qui ne connaissent pas, c’est le “plus haut” mont de la chaîne des Laurentides, une très vieille chaîne montagneuse qui passe au nord ouest de Montréal. Avec l’érosion il ne reste plus grand chose de très haut, mais toute la région est extrêmement vallonnée, ce sont des collines / monts qui s’enchainent à perte de vue. Du coup, aucune grosse ville et de la forêt à plus savoir qu’en faire. Et à quasiment chaque détour de la route, un lac. C’est pas compliqué, la région c’est : des collines et des lacs. Avec quelques petits villages tous mignons.

Donc, arrivée le samedi, on pose les affaires, et on va se balader le long du lac qui est à 2 pas de notre appart’. Grosse farniente au soleil sur un ponton, on profite de l’eau (oui oui, je n’ai pas mis les photos, mais on s’est baigné ! Sophie plus que moi, je croyais que l’eau serait beaucoup plus fraiche :p) puis retour à l’apprart. Première balade avec quand même une bonne grosse boucle.

Le lendemain, direction le mont Tremblant qui est juste à côté ! Passage par l’office du tourisme où on nous dit que les pistes ne sont pas accessibles à la rando pour cause de compétition de descente (VTT) donc on se rabat sur une petit rando … ce qui n’est pas du gout de la miss qui décide donc, armée de son plan, de nous concocter un beau petit parcours ! Et c’est parti pour 7H de marche ! C’était génial. Je ne sais pas exactement combien de km on a fait, autant à plat qu’en dénivelé, mais on en aura fait ! On est passé par des petits sentiers tout mignons, on a remonté les pentes des pistes, puis, après une petite escale arrivés tout en haut, on les a redescendu à moitié en courant. Petite pause le long de la piste de descente et au bas des pistes où c’était la grosse ambiance, et on repart pour la voiture.

Et là on a découvert le “mauvais” côté d’avoir autant de lac : les moustiques ! Des vampires. Mais bon, balade géniale, le coin est vraiment agréable et on a eu de la chance avec le temps ! Du coup le lendemain (lundi) on est allé se balader au village de Mont Tremblant (qu’on n’avait pas eu le temps de bien visiter la veille, on voulait pas trop trainer pour le retour) Et là, deuxième truc moche ici : les berges des lacs sont quasiment totalement des propriétés privées … du coup tu te balades, tu passes devant les maisons, t’aperçois le lac à travers les branches d’arbres des jardins, mais pas touche. Frustrant. Très.

Enfin bon, l’un dans l’autre, excellent WE ! Et je recommande vivement le coin ! C’est pas loin de Montréal, facile d’y aller, et pour les amoureux de la rando (à pied ou à vélo et même en roller pour certaines parties goudronnées) c’est pas loin du paradis :) Voilou. Et les cuisses et les mollets se souviendront longtemps de ce WE :)

IKImageView and kCGErrorIllegalArgument

RAAAHHH !!! Putain de SDK de con ! Bon, belle entrée en matière pour un post qui ne servira probablement qu’à ma petite mémoire défaillante, mais bon, si jamais un jour quelqu’un d’aussi tordu que moi rencontre le même problème, au moins Google devrait lui renvoyer cet article où il y trouvera son bonheur :) (enfin, j’espère !)

Le problème : Vous avez une application qui utilise une IKImageView pour afficher des images, les manipuler, etc. Cet IKImageView, vous l’avez overridé pour lui rajouter quelques fonctionnalités, comme par exemple la possibilité de passer en plein écran. Et là, c’est le drame ! Votre IKImageView marche bien quand il n’est pas en plein écran, mais dès que vous passez en fullscreen, paf, écran blanc uni, avec les laconiques messages d’erreur suivants dans votre log :

<Error>: kCGErrorIllegalArgument: CGSGetSurfaceBounds
<Error>: kCGErrorFailure: Set a breakpoint @ CGErrorBreakpoint()
         to catch errors as they are logged.

Hum … petite recherche sur le net, et là, pfff, aucune info (en tout cas à l’heure d’écrire ces lignes) En tout cas, aucun ressemblant de près ou de loin à mon setup.

Solution : Dans mon cas, j’avais un IBoutlet nommé window. J’utilise cet outlet pour faire de mon ImageView le first responder, lorsque je passe en plein écran (ça me permet d’être sur que mon ImageView récupère bien les évènements clavier / souris en fullscreen au lieu d’un autre élément de mon appli en background) Et c’est précisément cet outlet à la con qui posait problème ! Visiblement, IKImageView utilise en interne un window, qui ne correspond pas à celui que moi j’avais setté. Du coup lorsuq’il passait en fullscreen, bah gros problème … Et comme ça break pas, impossible de débugger. Sans compter que le “Set a breakpoint …” j’ai pas réussit à le faire marcher … vive le message d’erreur utile.

Bref, pour conclure, si vous créez une classe héritant de IKImageView, bannissez window de vos noms de variable. Pour ma part, j’utilise myWindow à la place, et je n’ai plus aucun bug !

Image Viewer v0.4

English will follow

Petite mise à jour de ImageViewer sur MacOSX :

  • Correction d’un bug aléatoire qui faisait que la lecture des .gif animés ne marchait pas.
  • Ajout d’une fonction de slide show, configurable via les préférences.

Prochaine mise à jour : J’aimerais ajouter un système permettant à l’ImageViewer de se mettre à jour lorsque le contenu change (par exemple si on supprime ou ajoute une image / un répertoire via le Finder, ImageViewer devrait se mettre automatiquement à jour)

——

Litle update to the MacOSX ImageViewer :

  • Fixed a bug that was breaking animated gif’s playback.
  • Added a slideshow function that you can configure through the preferences panel.

Next release : I want to make it update on file system change (if you add / remove an image via the Finder, the ImageViewer should update itself automatically)

Le code source / The source code : ImageViewer.v0.4

New York et Lúnasa

Un petit post “ma life” pour changer ! Le WE du 19 mars, on a eu l’occasion d’aller passer 4 jours (du samedi au mardi) à New York, pour l’occasion du passage des Lúnasa, groupe de Musique celtique dont ma douce est fan :) Bref, levé le samedi à 4H30, avion à 8H30, arrivée vers 11H, et c’est parti pour la visite !

Nous étions dans un petit hôtel dans le “upper est side” (côté est de Manhattan, à 5 minutes de Central Park) On a passé samedi et dimanche à marcher, dans Central Park, un peu partout dans Manhattan sans vraiment savoir où on allait ni où on était, on est passé à la New York Public Library, dans Central Park (à éviter le WE pour les agoraphobes :)) et finalement, un petit tour au 86ème étage de l’Empire State Building. A et quelques arrêts et détours par les boutiques, marchés, magasins et autres buildings impressionnants :)

Lundi, temps pourri, froid et pluie … du coup tentative d’aller jusqu’à Soho à pied qui s’est finalement transformée en Rockfeller Center (grandes galeries commerçantes couvertes) à l’heure du déjeuner … Donc surpeuplé de New Yorkais en costumes en train de manger. Et le soir, concert des Lúnasa. J’ai adoré. Et pourtant, je suis pas fan de musique celtique, mais je sais pas, la salle était bien, et sur scène ça rendait super bien. Bonne ambiance, groupe sympa, super bon souvenir !

Voilou, pour conclure, New York en un mot : “trop”. Trop grand, trop de monde, trop copieux (les plats) trop tout en fait :) Mais faudra qu’on y retourne, j’ai pas pu aller voir la statut de la liberté et 2/3 autres trucs à touriste :)

Pour voir les autres photos, c’est ici : http://gallery.pcitron.fr/2011.03.19.New.York/

 

 

C++ et mutable

Petite note à mon blog suite à la découverte du mot clef mutable en C++. Oui, même après 6 ans de développement, je continue de découvrir des trucs qui visiblement font pourtant partie de la base :) C’est plutôt cool de bosser enfin sur des projets développés par des têtes ! Mais trêve de blablah, explication !

On connait tous le mot clef const. Il est là pour garantir qu’un objet ne sera pas altéré / modifié. Un des exemples le plus courant concerne les “getter”, ces petites fonctions souvent inline qui permettent d’accéder à une variable membre en lecture seule. Par exemple :

class SceneNode
{
public:
    Matrix GetAbsoluteTransformation(void) const
    {
        // root node
        if (m_Parent == NULL)
            return m_RelativeTransformation;

        return m_Parent->GetAbsoluteTransformation() * m_RelativeTransformation;
    }
private:
    Matrix       m_RelativeTransformation;
    SceneNode *  m_Parent;
};

Ici, const garantit que GetAbsoluteTransformation ne modifie pas le contenu de l’instance de SceneNode. Ce qui est parfaitement logique et sain conceptuellement parlant.

Imaginons maintenant que l’on veuille optimiser un peu tout ceci en utilisant un cache de la matrice : en gros, on stocke en interne le résultat du calcule et tant qu’il n’y a pas de transformation, on se contente de renvoyer le résultat. Par exemple :

class SceneNode
{
public:
    const Matrix & GetAbsoluteTransformation(void) const
    {
        if (m_NodeFlags & RECALC_ABSOLUTE_TRANSFORMATION)
        {
            if (m_Parent == NULL)
                m_CachedAbsoluteTransformation = m_RelativeTransformation;
            else
                m_CachedAbsoluteTransformation = m_Parent->GetAbsoluteTransformation() * m_RelativeTransformation;
            // remet le flag a 0 pour ne pas avoir à recalculer au prochain appel
            m_NodeFlags &= ~RECALC_ABSOLUTE_TRANSFORMATION;
        }
        return m_CachedAbsoluteTransformation;
    }
private:
    Matrix       m_CachedAbsoluteTransformation;
    Matrix       m_RelativeTransformation;
    SceneNode *  m_Parent;
};

En gros, à chaque fois qu’une modification est apportée à la transformation d’un noeud (que ce soit le parent ou le noeud courant) on active un flag qui indique à la fonction GetAbsoluteTransformation de recalculer la matrice. Et quand ce flag est nul, on renvoie simplement le résultat.

Le problème qui se pose ici (hormis le fait que le code ci-dessus ne compilera très certainement pas à cause du const) c’est que l’on a une fonction qui, conceptuellement, ne modifie pas le contenu de l’instance, mais dans la pratique, si ! En effet, quand on recalcule le cache, on ne modifie pas le contenu logique de la classe : on ne modifie pas sa position, sa rotation, le contenu de ses différents états. MAIS on modifie quand même une variable membre, et donc le compilateur fait chier et on doit virer le const !

Et c’est là qu’intervient notre mot clef mutable : il permet d’autoriser la modification d’une variable membre par une méthode const ! Et notre exemple précédent devient :

class SceneNode
{
public:
    const Matrix & GetAbsoluteTransformation(void) const
    {
        // le contenu ne change pas
    }
private:
    mutable Matrix  m_CachedAbsoluteTransformation;
    Matrix          m_RelativeTransformation;
    SceneNode *     m_Parent;
};

Et là, le compilateur ne râle plus ! On a donc un getter parfaitement sécurisé, qui garantit la constance de l’instance sur laquelle il est appelé, tout en autorisant le caching du résultat !

Une petite note toutefois concernant ce mot clef : attention à son utilisation ! Il existe le risque de l’utiliser pour corriger de façon fonctionnelle un problème conceptuel ! (oui, c’est bizarre comme phrase, mais bon en gros si une méthode const modifie le contenu de sa classe, c’est souvent un défaut de conception qui peut être dangereux, alors en croyant le “corriger” en utilisant mutable, on ne fait en fait que masquer le réel problème :))

Sources :
http://msdn.microsoft.com/en-us/library/4h2h0ktk(v=vs.80).aspx
http://www.highprogrammer.com/alan/rants/mutable.html

3DMagix et IllusionMage, grosse arnaque …

Petit post “militant” suite à ce que j’ai lu ici : 3DMagix and IllusionMage, scam or open source leeches?

Et ci-dessous le petit lien à copier coller et foutre quelque part sur votre site si vous aussi ce genre de truc vous énerve profondément et que vous voulez y faire quelque chose (la multiplication de ce lien a pour but d’associer les mots clefs 3DMagix, 3DMagixPro et IllusionMage à un lien redirigeant sur le site officiel de Blender)

3DMagix, 3DMagixPro, IllusionMage, scam