Qualité audio des Smartphones en 2011

October 23rd, 2011 No comments

HTC Sensation XE

Introduction

Ce petit article n’a pas la prétention d’être exempt d’erreurs, il est écrit par un physicien audiophile et non un ingénieur du son. Le but de celui-ci est avant tout de vulgariser des concepts qui peuvent sembler obscurs aux néophytes. Vous trouverez des informations bien plus précises sur des sites spécialisés et notamment sur GenerationMp3.

Le problème avec la mesure de la qualité audio d’un appareil, c’est qu’elle est très subjective. Chacun perçoit la musique de manière différente car nous n’avons pas la même éducation musicale, la même oreille et les mêmes attentes en ce qui concerne la musique. Difficile donc de juger si un son est « bon » ou bien s’il est « mauvais » . Parler de “mauvais son” et de “bon son” est un abus de langage, il vaut mieux parler de qualité de la sortie audio, c’est d’ailleurs le sujet de cet article

Pour les appareils électroniques, on considère que le signal n’est globalement pas abimé en étant stocké, ni même décompressé par le processeur (vers 44100Hz, 16Bit, Stereo). Le principal responsable de l’altération du signal est le composant DAC (le convertisseur digital vers analogique) qui contient aussi un amplificateur sur ce type d’appareil.

Actuellement sur les Smartphones haut de gamme le son est de bonne qualité, on comparera le son avec un lecteur MP3 IAudio d’excellente facture : le Cowon IAudio 9.

Fast Track Pro est le système utilisé.

Donc pour juger la qualité d’une sortie audio on cherche à vérifier comment retranscrit le lecteur, un signal que l’on a créé et que l’on connait. Par là j’entends que l’on crée un fichier contenant un signal audio codé en numérique. On lit ce fichier avec le lecteur et en sortie on récupère le signal analogique soit :

  • directement avec la prise jack (20000 Ohm)
  • avec un casque (ici AKG 32 Ohm) directement avec un microphone de très bonne qualité si l’on veut tenir compte de l’impédance ajoutée par celui-ci.

Les tests suivants ont été réalisés à volume maximum ce qui permet d’accentuer la distorsion que l’appareil inflige au signal. En effet, certains lecteurs détériorent grandement le signal à volume max.

Pour le test, le casque utilisé est de 32 Ohm, l’intensité est plus importante qu’un casque avec une plus haute impédance. L’amplificateur est plus sollicité donc travaille moins bien. De plus, on pousse le son à fond pour avoir une plus grande intensité. Ces tests sont réalisés par des professionnels. Vous trouverez à la fin de cette article les sources. Le logiciel utilisé est RightMark Audio.

En comparant le signal donné et le signal que nous renvoit le casque on peut discuter quantitativement de la qualité d’une sortie audio. Les résultats doivent être reproductibles et comparables sinon cela n’a pas d’intérêt.

La réponse en fréquence

Cette mesure ne permet pas de dire si le son est agréable, mais uniquement si le son qui sort des écouteurs est le son tel qu’il est enregistré sur le fichier audio. Pour comprendre cette partie, il faut savoir ce qu’est un signal audio. Très rapidement, un signal audio est une information provenant d’un émetteur et attendant un récepteur composé d’une multitude de signaux sinusoïdaux purs avec des fréquences différentes.

Rappel sur la fréquence :

Une fonction sinusoïdale est décrite par sa phase ϕ (“décalage par rapport à l’origine“), son amplitude Ĝ et sa fréquence (ici pulsation ω). On peut l’écrire de cette manière.

Ici, ce terme contient toutes les fonctions sinusoïdales, que ce soit un cosinus ou un sinus. Le cosinus étant juste un sinus déphasé. Mais c’est vrai que l’on s’en fiche, continuons…

Voila deux signaux sinusoïdaux mais de fréquences différentes.

Au-dessus fréquence basse (son grave), au-dessous fréquence élevée (son aiguë)

Un signal quelconque peut être décomposé en une somme de signaux sinusoïdaux. Par exemple : ci-dessous avec le signal audio composé en noir qui est en fait la somme pondérée des signaux en vert, rose, bleu, rouge etc… Ainsi notre oreille perçoit le signal comme une somme de signaux sinusoïdaux de fréquences différentes.

Le signal noir est la somme pondérée des autres signaux...

 

Grâce à un outil mathématique appelé “transformée de Fourier” on peut décomposer le signal du dessous en une somme de sinus de fréquences différentes avec une intensité différente. C’est ce qu’on voit au-dessus (à chaque pic correspond une intensité particulière pour une certaine fréquence). Plus le pic est grand plus la fréquence correspondante est “présente”.

Revenons à nos moutons, on cherche à déterminer par rapport à un signal envoyé si toutes les fréquences sont bien restituées et dans les mêmes proportions. Si j’envoie un signal « plat »  et que les basses sont plus intenses que les aiguës c’est que le lecteur ne restitue pas correctement le son. C’est mauvais ou alors un équaliseur altère le signal.

Les limites de perception de l’oreille humaine se situent entre 20Hz et 20Khz. Mais globalement on se fiche de cette bande passante car la plupart des appareils électroniques sont capables de restituer un signal dans cette gamme de fréquence et puis l’oreille humaine ni verra que du feu même si l’on est entre 30 Hz et 19 KHz. Non ce qui nous intéresse c’est si la restitution est « uniforme ».

A propos de l’unité Décibel :

Partout dans le monde, pour mesurer la puissance d’une onde sonore (ou plutôt pour comparer deux puissances) on utilise une unité appelée Décibel. C’est un nom un peu barbare en l’honneur de Mr Bell et inventé par les ingénieurs des laboratoires Bell pour quantifier l’atténuation d’un signal Audio sur une liaison téléphonique. C’est une fonction logarithmique (pourquoi, parce que notre oreille est un récepteur logarithmique !!) de rapport de puissance (ce que l’on envoie par rapport à ce que l’on reçoit). On multiplie enfin par 10 pour avoir une unité plus pratique (d’où le nom déci-bel).

Gain en décibel, permettant de comparer deux puissances P1 et P0

Si la puissance du signal de sortie est égale au signal de puissance de l’entrée, le logarithme vaut 0 (en effet log(1)=0) et donc pas d’atténuation. Si la puissance du signal de sortie est 10 fois plus faible (log(10) = 1) donc on aura une atténuation de 10 dB (-10dB) et s’il est 100 fois plus faible -20dB, 1000 fois -30 dB.

Pour mesurer la réponse en fréquence on envoie donc un signal et on mesure l’atténuation (ou l’amplification) de certaines fréquences. On note [+ x dB, – y dB].

Exemple :

Pour le HTC Sensation, directement sur le jack (en blanc) et avec un casque (en vert)

On s’intéresse d’abord à la courbe blanche. Sur celle-ci nous voyons que la réponse en fréquence est plutôt bonne (attention c’est une échelle logarithmique) entre 40Hz et 15 Khz. +0.05 dB,-0.34dB au bord. Par contre quand on rajoute la résistance du casque c’est un peu moins bon +0.71 dB (pour les basses), -0.15 dB pour les aiguës. Comme on l’a vu c’est normal le courant augmente et l’amplificateur souffre.

Voici l’évolution de la réponse en fréquence pour quelques Smartphones :

Sans casque Réponse en fréquence (dB) Étendue
HTC Desire HD 0,09 -0,44 0,53
HTC Sensation XE 0,05 -0,34 0,39
Cowon IAudio 9 0,03 -0,16 0,19
Apple IPhone 4S 0,02 -0,11 0,13
Samsung Galaxy S II 0,04 -0,09 0,13
Apple IPhone 4 0,01 -0,07 0,08
LG Optimus 2X 0,01 -0,03 0,04

Plus l'étendue est faible plus la réponse en fréquence est bonne. Les HTC sont les moins bons ici.

En charge les résultats sont tout de suite différents mais bien plus intéressants :

Avec casque Réponse en fréquence (dB) Étendue
Samsung Galaxy S II 1,05 -0,22 1,27
HTC Sensation XE 0,71 -0,15 0,86
HTC Desire HD 0,09 -0,44 0,53
LG Optimus 2X 0,14 -0,04 0,18
Apple IPhone 4S 0,05 -0,1 0,15
Apple IPhone 4 0,01 -0,07 0,08

Le Samsung Galaxy S II est le moins bon. Je suis désolé je n'ai pas de valeur pour le Cowon IAudio 9 avec un casque. Les téléphones d'Apple se comportent très bien !

Le niveau de bruit :

Quand le son sort de l’appareil celui-ci peut être perturbé par des signaux parasites qui peuvent venir par exemple du champ Électromagnétique environnant (le téléphone communique) si le blindage de l’appareil n’est pas terrible, cela peut venir aussi du processeur etc… (Rendez vous ici pour écouter ce bruit sur le Samsung Galaxy S II http://soundcloud.com/anandtech/galaxysii-cpu-edge-noise )
Ici la mesure se fait en dB (A), c’est l’unité retenue pour représenter les niveaux sonores en tenant compte de la sensibilité (selon la fréquence) de l’oreille humaine (l’humain entend moins bien les graves que les aiguës). Alors on fixe comme origine 40 dB au dessus du seuil d’audibilité. C’est à dire qu’à 0 dB(A) on est 40 dB au dessus du seuil où l’on entend plus rien.

On classe ci-dessous  les appareils en fonction de leur niveau de bruit.

Sans casque Noise Level (dB(A))
Samsung Galaxy S II -91,4
Apple IPhone 4S -91,2
HTC Desire HD -90,6
Cowon IAudio 9 -90,5
HTC Sensation XE -90,2
Apple IPhone 4 -90,1
LG Optimus 2X -90,1

Le Samsung Galaxy S II est ici le meilleur dans cette catégorie en tout cas sans charge. C'est à dire sans casque.

Sans casque Noise Level (dB(A))
HTC Desire HD -93,2
Apple IPhone 4S -91,3
Apple IPhone 4 -90,4
Samsung Galaxy S II -90
LG Optimus 2X -89,8
HTC Sensation XE -89,1

Le HTC desire HD est roi. Et le HTC Sensation XE le moins bon.

Je tiens à modérer ces résultats, soyons honnêtes le HTC Sensation XE à un rapport signal bruit de -89 dB ce qui signifie que le bruit est 77 000 fois trop faible pour être entendu par l’être humain. Pour le Desire HD, c’est 200 000 fois…

La gamme dynamique :

C’est la capacité qu’a un appareil à reproduire en même temps un son peu intense et très intense. Pour éviter la triche, on mesure uniquement les signaux qui ne subissent pas de distorsion (grossièrement de déformation). Par exemple si un appareil est capable de produire des sons pour une fréquence donnée de 9 dB(A) à 1 dB(A), la gamme dynamique vaut 8 dB(A). Plus cette gamme (dynamic range) est grande et mieux c’est !

Nom Dynamic Range (dB(A))
HTC Desire HD (Casque) 92,90
Samsung Galaxy S II 91,90
Apple iPhone 4S (Casque) 91,30
Apple iPhone 4S 91,20
Cowon Iaudio 9 90,50
Apple iPhone 4 (Casque) 90,40
HTC Desire HD 90,40
Samsung Galaxy S II (Casque) 90,20
HTC Sensation 90,20
HTC Sensation (Casque) 90,10
LG Optimus 2X 90,10
Apple iPhone 4 90,00
LG Optimus 2X (Casque) 89,90

Avec un casque le HTC Desire HD est encore une fois le meilleur suivi des IPhone et du Samsung. Le HTC Sensation semble à la traine...

Le taux de distorsion harmonique :

La distorsion harmonique, notée THD est une spécificité des amplificateurs (ou préamplificateurs). Comme nous l’avons vu tout à l’heure on peut décomposer n’importe quel signal audio sous forme de signaux sinusoïdaux. Le signal prépondérant est le fondamental (ce signal donne la hauteur de la note), les autres les harmoniques (elles donnent le timbre, la note LA du piano ne s’entend pas comme le LA d’une clarinette). En fait plus la quantité d’harmoniques est grande plus le signal est précis :

Plus le nombre d'harmoniques augmente plus le signal reconstitué est proche du signal carré.

Pour conclure le taux de distorsion harmonique est le résultat d’un calcul mathématique ayant pour but de comparer le signal de sortie (ce qui sort du jack) et le signal d’entrée (le fichier audio). Plus ce taux est important plus la différence est importante et donc plus l’amplificateur est médiocre.

Nom THD (%)
Apple iPhone 4S 0,002
Apple iPhone 4 (Casque) 0,0036
Samsung Galaxy S II 0,0042
Cowon Iaudio 9 0,0048
Apple iPhone 4S (Casque) 0,0068
Apple iPhone 4 0,0068
LG Optimus 2X (Casque) 0,0098
LG Optimus 2X 0,011
HTC Sensation 0,012
Samsung Galaxy S II (Casque) 0,013
HTC Desire HD 0,014
HTC Sensation (Casque) 0,019
HTC Desire HD (Casque) 0,02

 

On remarque que cette fois ci le Desire HD est en retrait en ayant le plus haut THD. Le HTC Sensation ne brille toujours pas. Par contre les IPhones sont vraiment bons.

Distorsion d’intermodulation + bruit :

C’est un phénomène complexe qui est la conséquence de la non linéarité du DAC. Si on a un signal avec deux fréquences différentes en entrée nous n’obtenons pas deux fréquences en sortie mais une multitude de signaux. Au premier ordre on voit bien ci-dessous deux pics secondaires en plus des deux pics de base ) gauche et à droite.

C’est ce phénomène qui est mesuré par l’IMD. Plus ce nombre est faible moins la distorsion est importante, mieux c’est.

Nom IMD (%)
Cowon Iaudio 9 0,0094
Apple iPhone 4S 0,012
Apple iPhone 4 0,012
LG Optimus 2X 0,016
HTC Sensation 0,021
Samsung Galaxy S II 0,066
Apple iPhone 4S (Casque) 0,071
Apple iPhone 4 (Casque) 0,092
LG Optimus 2X (Casque) 0,111
HTC Desire HD 0,517
HTC Sensation (Casque) 0,522
Samsung Galaxy S II (Casque) 0,647
HTC Desire HD (Casque) 0,728

Le HTC Desire HD a encore de grandes difficultés ici. Le Samsung Galaxy S II galère aussi (c'est relatif). L'IPhone 4 est encore une fois très très bon.

Diaphonie Stéréo :

Si on envoie un signal dans l’oreille droite. Le signal passe t’il aussi à gauche ? Et bien oui ! On compare dans ce test la puissance du signal à gauche par rapport à celui à droite. Plus ce rapport est faible, plus la stéréo est bonne !

Nom Stereo crosstalk (dB)
Apple iPhone 4S -93
HTC Desire HD -92,6
HTC Sensation -91,1
Cowon Iaudio 9 -90,3
Samsung Galaxy S II -89,7
Apple iPhone 4 -89,6
LG Optimus 2X -89,2
HTC Sensation (Casque) -70,6
Apple iPhone 4 (Casque) -68,4
Apple iPhone 4S (Casque) -66,7
Samsung Galaxy S II (Casque) -49,4
LG Optimus 2X (Casque) -35,1
HTC Desire HD (Casque) -17,9
Le HTC Sensation est une fois n’est pas coutume devant tout les autres ! Le HTC Desire HD par contre est bien plus mauvais. Le Samsung Galaxy S II est aussi en retrait.

Conclusion

Pour finir comparons deux smartphones haut de gamme avec trois appareils (sans casque) :

  • La Nintendo DS Lite réputée pour avoir un son très mauvais.
  • Le lecteur Mini Disc Sony MZ-R3 représentant le haut de gamme… Il y a 15 ans.
  • Le Cowon IAudio 9, un excellent lecteur contemporain.
Etendue réponse en Fréquence (dB) Noise level (dB(A)) Dynamic Range (dB(A)) THD (%) IMD + Noise (%) Stereo CrossTalk (dB)
Sensation 0,39 -90,2 90,2 0,012 0,021 -91,1
IPhone 4S 0,13 -91,2 91,2 0,002 0,012 -93
Nintendo DS Lite 8,78 -66 64,5 1,8 3,836 -69,1
Mini Disc Sony MZ-R3 1 -86 86,1 1,658 2,128 -67,1
Cowon Iaudio 9 0,12 -79 79 0,0058 0,032 -79,4

Comparaison de deux smartphones avec trois autres appareils. Les unités sont modifiées pour être représentées sur le même graphique.

On voit sur ce graphique que relativement à la DS et au MiniDisc, les smartphones et le lecteur MP3 sont relativement proches. Globalement la qualité audio est là et je doute que l’oreille humaine avec un casque à moins de 500 € puisse y voir quelque chose. Ce n’est pas avec les écouteurs Beats de Dr. Dre que l’on verra une différence flagrante.

On a vu que la qualité Audio évolue avec l’impédance du casque. Plus l’impédance est faible, plus l’ampli abime le signal.

Comme je l’expliquais en introduction, la qualité audio dépend beaucoup de chacun et l’objectif principal est de se faire plaisir. Ce matériel n’est de toute manière pas adapté aux professionnels et il n’a même pas été conçu pour ça. Vous pouvez adapter le signal à vos goûts : si vous aimez les basses vous pouvez régler l’équaliseur en conséquence (c’est d’ailleurs ce que fait la technologie Beats de HTC) ou acheter des écouteurs favorisant les basses.

La qualité audio dépend aussi de beaucoup d’autres éléments que nous n’avons pas pris en compte, par exemple :

  • Écoutez vous la musique dans un endroit bruyant ? Si vous êtes dans le métro, mais avec un casque très isolant, le bruit extérieur sera audible. Le Noise Level avec ses -80 dB(A) semble ridicule à côté…
  • Que vaut votre casque ? Si votre casque force sur les basses, la réponse en fréquence sera totalement différente…
  • Quelle est la qualité de vos fichiers musicaux ? Peut être écoutez vous du streaming ? La compression est souvent destructrice (lossy).
  • Avez vous une très bonne oreille ? Plus on vieillit, malheureusement, plus notre oreille perd en sensibilité. C’est un fait…
  • etc

L’autre question à se poser est : êtes vous un puriste ?

  • Avez vous un casque valant plusieurs centaines d’euros ou des intras à 500 € et un MP3 d’une très grand marque (souvent cher et moche ‘Je rigole’) ?
  • Écoutez vous constamment de la musique compressée en FLAC (lossless) et avez vous mis tout vos MP3 (lossy) à la corbeille ?

Peut être que la qualité audio n’est pas l’élément principal à prendre en compte lors de l’achat de votre smartphone vu le peu de différences entre-eux. En tout cas cela ne semble pas être une question prépondérante lors de l’achat d’un téléphone.

Sources :

GSMArena

About Stereos

Wikipedia

Engadget

ElectroKrishna

ArnandTech

Remarques :

Si vous avez des remarques n’hésitez pas, je suis toujours à l’écoute. Je suis audiophile mais pas professionnel, les informations présentes ici sont donc à remettre dans leur contexte.

Rémi MEVAERE

Cours particuliers sur Lille

August 5th, 2011 No comments

Vous cherchez un soutien en Mathématiques, en Physique ou en Chimie pour vous ou votre enfant sur Lille ? Vous trouverez sur le site suivant toutes les informations pour préparer votre future réussite. Mais aussi une banque de données, des informations sur le CESU, des documents me concernant et quelques conseils dans les matières que j’enseigne : Mathématiques, Physique, Chimie.

http://www.coursparticuliers-lille.fr

Categories: Etrangetés Tags:

Detecting a Delphi executable, DVCLAL, Manifest and PackageInfo

June 7th, 2011 2 comments

I will try to improve my English in this post. I understand that I must work on it! In this post I will try to expose several ways to detect a Delphi application.

First Part DVCLAL and licensing information

Yesterday I was asking me a question. What information could we extract from a Delphi executable about the compiler, the license and all these things?

First thing I done was just compiling a simple application form (Delphi XE) and watch if there is something in it.

I have three Executable:

  1. With a valid license
  2. With the same valid license
  3. With another valid license from a friend
  4. Without license

MD5

  1. aa937b519d3dc7748658339d74beab71
  2. 3a052680d1baa16b53a7376e94d88bb6
  3. eb66631ce3aa2ab2bfeb27779164dfa1
  4. 35f29fbcbf468dc1a683f742893d54b1

The files are different, even the first and second (which are compiled with the same license in less than 2 minutes). Something is added in the file, like a date or a time.

DVCLAL – Resource Name for RC_DATA

  1. 000DEF00  26 3D 4F 38 C2 82 37 B8 F3 24 42 03 17 9B 3A      &=O8‚7¸ó$B••›:
  2. 000DEF00  26 3D 4F 38 C2 82 37 B8 F3 24 42 03 17 9B 3A      &=O8‚7¸ó$B••›:
  3. 000DEF00  26 3D 4F 38 C2 82 37 B8 F3 24 42 03 17 9B 3A      &=O8‚7¸ó$B••›:
  4. 000DEF00  26 3D 4F 38 C2 82 37 B8 F3 24 42 03 17 9B 3A      &=O8‚7¸ó$B••›:

DVCLAL (Delphi Visual Component Library Access License) are the same for the three files, this is pretty strange.

To detect the change between file I am using the command line tool “compare” included in Windows. So as you can see the differences between file are exactly at the same offset and are equal. It is unbelievable to store huge license information in 16 bytes (word) or 32 bytes (dword).

In green this is the beginning of the executable (low offset). In MSDN documentation you can find info about PE (Portable Header which is the structure of executable files).

If we open it in Hex Edit.

The PE chars follow by two null values are signature of the beginning of the executable. After that we have IMAGE_FILE_HEADER.

Syntax

typedef struct _IMAGE_FILE_HEADER {

WORD  Machine;

WORD  NumberOfSections;

DWORD TimeDateStamp;

DWORD PointerToSymbolTable;

DWORD NumberOfSymbols;

WORD  SizeOfOptionalHeader;

WORD  Characteristics;

} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

 

We have in HexEdit the first word which is 4C01, and the second one NumberOfSections 0A00. The DatetimeStamp is 14DEE84D. Clearly it’s the time information of the build.

 

TimeDateStamp

The low 32 bits of the time stamp of the image. This represents the date and time the image was created by the linker. The value is represented in the number of seconds elapsed since midnight (00:00:00), January 1, 1970, Universal Coordinated Time, according to the system clock.

So let’s return to DVCLAL, and see when it is used by Delphi. So I search the string DVCLAL in Embarcadero folder. And the only file which is return is Sysutils.pas. (For copyright reasons I can’t share the code of the function in Delphi main pascal files)

The ALR function returns a pointer handle that can be used to obtain a pointer to the first byte of the specified resource in memory. Here the string DVCLAL.
The GDAL function is testing the value of the DVCLAL and if there is a problem, the exe raise an exception.

The RPR function is testing the validity of DVCLAL and if there is a problem, raises an exception.

I don’t know if RPR is used in the last version of Delphi but in older version, when the exe was loading module he was launching the procedure RPR.

So in conclusion, just understand that DVCLAL is one way to detect Delphi app, but it is not secure, you could easily delete this value and nothing will appear.

Manifest file attached to the executable and PackageInfo

In the RC_DATA resource of Delphi executable you could find a Resource named PackageInfo. You will find more information in sysutils.pas. (Function GetPackageInfo)

A variable of type PackageInfoTable provides information about initializing or finalizing a series of package units.

The manifest file is in the resource type RC_Manifest with the name 1036 could help you to detect if the compiler is Delphi. (CodeGear Rad Studio in Assembly Name)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    type="win32"
    name="CodeGear RAD Studio"
    version="15.0.3953.35171"
    processorArchitecture="*"/>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        publicKeyToken="6595b64144ccf1df"
        language="*"
        processorArchitecture="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="asInvoker"
          uiAccess="false"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
 

So I hope it will help you if you need to detect Delphi application. But the Application could be crypt, the resource could be easily modified and the DVCLAL deleted.

Have a nice day ;)

Listing, Adding, Editing, Deleting resources of EXE, DLL … Using Win32 API with Delphi

June 3rd, 2011 No comments

Introduction

Today, I tried to work with resources included in a File. The file is an executable like DLL or EXE. There are some useful functions in the Win32 API that could help us, you don’t need to fully understand PE_FILE and how work an executable to change the resources. I would like to show you how to use it in Delphi.

First Step : Listing all the resources

How to open an executable file ?

LoadLibraryEx is described on this page of MSDN

var
           hinstance: HMODULE;
begin
           hinstance := LoadLibraryEx(PChar('c:\the_file.exe'), 0, LOAD_LIBRARY_AS_DATAFILE);

           //HERE code with hinstance

           FreeLibrary(hinstance);

To list all the resources we will use the EnumResourceTypes (function also described in MSDN) which is calling the function CallbackEnumResTypes.

EnumResourceTypes Function

Enumerates resource types within a binary module.

Syntax

BOOL WINAPI EnumResourceTypes(
  __in_opt  HMODULE hModule,
  __in      ENUMRESTYPEPROC lpEnumFunc,
  __in      LONG_PTR lParam
);

Parameters

hModule [in, optional]
Type: HMODULE 

lpEnumFunc [in]
Type: ENUMRESTYPEPROC 

A pointer to the callback function to be called for each enumerated resource type. For more information, see the EnumResTypeProc function.

lParam [in]
Type: LONG_PTR 

An application-defined value passed to the callback function.

Return Value

Type: BOOL

Returns TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.

Remarks

For each resource type found, EnumResourceTypes calls an application-defined callback function lpEnumFunc, passing each resource type it finds, as well as the various other parameters that were passed to EnumResourceTypes.

 EnumResourceTypes(hinstance, @CallbackEnumResTypes, Integer(ListBox1.Items));

//The first parameter is the Hinstance of the Executable, the second one is pointing on a function which will received the result of EnumResourceTypes and the last one is what you want !! Here a pointer to Listbox1.Items 

The ResType parameter is described by MSDN

Type: LPTSTR

The type of resource for which the type is being enumerated. Alternately, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID is the integer identifier of the given resource type. For standard resource types, see Resource Types. For more information, see the Remarks section below.

The return value is the specified value in the low-order word and zero in the high-order word.

What is stdcall ?  I have forgotten ! :)

When you declare a procedure or function, you can specify a calling convention using one of the directives register, pascal, cdecl, stdcall, and safecall. Calling conventions determine the order in which parameters are passed to the routine. They also affect the removal of parameters from the stack, the use of registers for passing parameters, and error and exception handling. The default calling convention is register.

  • register Left-to-right Routine Yes
  • pascal Left-to-right Routine No
  • cdecl Right-to-left Caller No
  • stdcall Right-to-left Routine No
  • safecall Right-to-left Routine No
function CallbackEnumResTypes(HInstance: HMODULE; ResType: PChar; OutList: TStrings): Integer; stdcall;
begin

if HiWord(Cardinal(ResType)) <> 0 then
OutList.Add(ResType) // The HighWord <> 0 This is strange MSDN explain us that hi-order word must be zero
else
OutList.Add(Format('Resource Number %d: Description %s', [loword(Cardinal(ResType)), StockResourceType(ResType)]));

EnumResourceNames(HInstance, ResType, @enumResNamesProc, Integer(OutList));  // Enum all the Resources

Result := 1;   // Continue The enumeration
end;

So we have used a function name StockResourceType wich are giving us a String describing the Type of the Resource (All the information on this page)


Function StockResourceType(ResType: PChar): string;
           const
           ResTypeNames: Array [1 .. 24] of String = ('RT_CURSOR',
           'RT_BITMAP',
           'RT_ICON',
           'RT_MENU',
           'RT_DIALOG',
           'RT_STRING',
           'RT_FONTDIR',
           'RT_FONT',
           'RT_ACCELERATOR',
           'RT_RCDATA',
           'RT_MESSAGETABLE',
           'RT_GROUP_CURSOR',
           'UNKNOWN',
           'RT_GROUP_ICON',
           'UNKNOWN',
           'RT_VERSION',
           'RT_DLGINCLUDE',
           'UNKNOWN', 'RT_PLUGPLAY',
           'RT_VXD',
           'RT_ANICURSOR',
           'RT_ANIICON',
           'RT_HTML',
           'RT_MANIFEST'
);
var
           ResID: Cardinal absolute ResType;
begin
           if ResID in [1 .. 24] then
                      Result := ResTypeNames[ResID]
           else
                      Result := 'UNKNOWN';
end;

What is absolute directive ?  I have forgotten ! :)

You can create a new variable that resides at the same address as another variable. To do so, put the directive absolute after the type name in the declaration of the new variable, followed by the name of an existing (previously declared) variable. We can here use Restype which is a Pchar in a particular address in a ResId function which is a Cardinal.

For the Callback function EnumResourceNames, this is the same thing.

BOOL CALLBACK EnumResNameProc(
  __in_opt  HMODULE hModule,
  __in      LPCTSTR lpszType,
  __in      LPTSTR lpszName,
  __in      LONG_PTR lParam
);

Parameters

lpszType [in]

Type: LPCTSTR

The type of resource for which the name is being enumerated. Alternately, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID is an integer value representing a predefined resource type. For standard resource types, see Resource Types. For more information, see the Remarks section below.

lpszName [in]

Type: LPTSTR

The name of a resource of the type being enumerated. Alternately, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID is the integer identifier of the resource. For more information, see the Remarks section below.


function EnumResNamesProc(module: HMODULE; ResType, ResName: PChar; list: TStrings): Integer; stdcall;
begin
           if HiWord(Cardinal(ResName)) <> 0 then
                      list.Add('  ' + ResName)
           else
                      list.Add(Format('  #%d', [loword(Cardinal(ResName))]));
           Result := 1; // Continue !
end;

Second Step : Adding, Editing, Deleting resources

UpdateResource Function

Adds, deletes, or replaces a resource in a portable executable (PE) file. There are some restrictions on resource updates in files that contain Resource Configuration (RC Config) data: language-neutral (LN) files and language-specific resource (.mui) files.

Syntax

BOOL WINAPI UpdateResource(
  __in      HANDLE hUpdate,
  __in      LPCTSTR lpType,
  __in      LPCTSTR lpName,
  __in      WORD wLanguage,
  __in_opt  LPVOID lpData,
  __in      DWORD cbData
);

Parameters

hUpdate [in]
Type: HANDLE 

A module handle returned by the BeginUpdateResource function, referencing the file to be updated.

lpType [in]
Type: LPCTSTR 

The resource type to be updated. Alternatively, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID is an integer value representing a predefined resource type. If the first character of the string is a pound sign (#), then the remaining characters represent a decimal number that specifies the integer identifier of the resource type. For example, the string “#258″ represents the identifier 258.

For a list of predefined resource types, see Resource Types.

lpName [in]
Type: LPCTSTR 

The name of the resource to be updated. Alternatively, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID is a resource ID. When creating a new resource do not use a string that begins with a ‘#’ character for this parameter.

wLanguage [in]
Type: WORD 

The language identifier of the resource to be updated. For a list of the primary language identifiers and sublanguage identifiers that make up a language identifier, see the MAKELANGID macro.

lpData [in, optional]
Type: LPVOID 

The resource data to be inserted into the file indicated by hUpdate. If the resource is one of the predefined types, the data must be valid and properly aligned. Note that this is the raw binary data to be stored in the file indicated by hUpdate, not the data provided by LoadIcon, LoadString, or other resource-specific load functions. All data containing strings or text must be in Unicode format. lpData must not point to ANSI data.

If lpData is NULL and cbData is 0, the specified resource is deleted from the file indicated by hUpdate.

cbData [in]
Type: DWORD 

The size, in bytes, of the resource data at lpData.

Return Value

Type: BOOL

Returns TRUE if successful or FALSE otherwise. To get extended error information, call GetLastError.

Adding

var
           FileHandle: THandle;
           Filebuffer: ShortString;
           Test: PChar;

Filebuffer := 'Something to add this is a string ! Not Unicode here ;)  ! ';
FileHandle := BeginUpdateReSource(PChar('c:\the_exe.exe'), False); // begin updating our resource
UpdateReSource(FileHandle, RT_RCDATA, 'THE_NAME_OF_THE_RESOURCE', 0, @Filebuffer[1], Length(Filebuffer));  // Updating the resource
EndUpdateReSource(FileHandle, False); // End of the update

Editing

UpdateReSource(FileHandle, RT_RCDATA, 'EXIST_NAME', 0,  @Filebuffer[1], Length(Filebuffer));  // Updating the resource, the EXIST_NAME resource exist !

Removing


Filebuffer := ''; // To delete just create something empty or clear !
UpdateReSource(FileHandle, RT_RCDATA, 'EXIST_NAME', 0,   @Filebuffer[1], Length(Filebuffer));  // Updating the resource, the  EXIST_NAME resource exist !

Third Step : And for a bitmap ?

This is a small piece of code which will give you an example of how to add a bitmap in resource… After that you will now how to add Cursor, Song etc…


var
           HInstance: THandle;
           bitmap: Pointer;
           FS: TFILESTREAM;
           dwSize: DWORD;
begin
           HInstance:= BeginUpdateResource(THE_EXECUTABLE_PATH, false);

           FS := TFileStream.Create(THE_BITMAP_PATH, fmOpenRead or fmShareDenyWrite); // Opening a TFileStream
           GetMem(bitmap, FS.Size + 1); // Get memory to add the Bitmap in memory
           FS.ReadBuffer(bitmap^, FS.Size); // Full this part of the Memory with Bitmap DATA
           dwSize := FS.Size; // Size of the Bitmap
           FS.Free; // Closing the TFileStream

           UpdateResource(HInstance, PWideChar(RT_BITMAP), '6805'  , LANG_SYSTEM_DEFAULT, bitmap, dwSize); // 6805 is the name, and the language is the default of my system

           EndUpdateResourceW(HInstance, false);
end;

I hope it will help you to use Resources.

Have a good week,

Help Science with your computer : Folding@Home

May 29th, 2011 No comments

Folding@home is the most powerful distributed computing cluster in the world, according to Guinness,and one of the world’s largest distributed computing projects. The goal of the project is “to understand protein folding, misfolding, and related diseases.”

I would like to share my experience about this program of distributed computing. First I have one powerful computer (Quad Core CPU and 2 GPU) and one server (okay it’is not a powerfull one, but it is enough for me and my several websites).

New software of Folding@Home V7

When I am coding, I am using a small part of the power of my system and my server is not overload ;) . So my computers could be useful to help science and research like all the servers of Google which are also supporting this project ! In only two months, I am  in the top five percent position. Let’s see the graph.

My rank in Folding@Home

Actually I am student and I can’t give money to charity association, and I don’t like this, I think this is the job of government. But I prefer being active on a global and worldwide project with a lot of peoples (1552132 peoples at this time, number of registration). This is, in my opinion, a form of donation !

Like me you could be a part of this adventure, don’t wait just click here !

Categories: Geek things Tags: ,

Some functions and properties of TIDPop3

May 11th, 2011 No comments

In the last post which was dealing with Indy. We have seen how to configure TIDPop3. Let’s see how to use this component.

In the uses dont forget to add the IDPop3 file which contains all the information for TIDPop3.

uses
Idpop3;
type
POP3Client: TIdPOP3;

The first thing I do is write a procedure to retrieve the status from the TIDPop3 :

procedure Thread_POP3.POP3Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string);
begin
Synchronize
( procedure begin
// USE AStatusText
end);
end;

// After the creation of POP3Client we can assign this event
POP3Client          := TIdPOP3.Create(nil);
POP3Client.OnStatus := POP3Status;

To connect to the server just use the procedure Connect, lets see other methods :

POP3Client.Connect; // Connection
POP3Client.login; // Use it to Connect

If you want to get the number of mails just use the function CheckMessages, and to get the mail the mail number I RetrieveMsgSize(I) :

FNbrMailsOnline := POP3Client.CheckMessages; // Retrieve the number of mails on the server
FTailleDernierMail := POP3Client.RetrieveMsgSize(FNbrMailsOnline); // Retrieve the size of the Last Mail

To delete a mail just do this :

POP3Client.Delete(I); // The mail will only be delete when you will disconnect
// If you want to cancel the deletion just use the
POP3Client.Reset; // Cancel the deletion

Now let’s see how to retrieve mails :

Tell Delphi where to find the TIDMessage class

uses
IDMessage;
type
Message: TIDMessage;

If you want to retrieve only the header of a mail (not the all mail, just the basics information) :

POP3Client.RetrieveHeader(Position_Mail, Message); // Retrieve only the header
POP3Client.Retrieve(Position_Mail, Message); // Retrieve the all mail

To retrieve a Raw Mail (the text without processing the mail in TIDMessage MIME parser) :

POP3Client.RetrieveRaw(Position_Mail, Down_MemStream);

And in conclusion, disconnection :

POP3Client.Disconnect; // Disconnection

Bye,

Peganza, Pascal Analyser 5 review

April 29th, 2011 1 comment

I’m in really good move since several days, I have never written so much in a blog. So let’s go for a new post about a fabulous tool named Pascal Analyser…

Is this tool in Rad Studio IDE?

 

When you are developing software and you want to build a solid code like a rock. You need some tools to give you “Metrics”. Metrics give you answers to the following questions:

  • How much files in your project? How much modules, lines, constants, class, variables?
  • Give you information about complexity of your code. How much Comments/Total lines in your code? What is the complexity of functions or procedures? About objects programming: What is the complexity of methods per class, the number of children and lot of other things?

To introduce the tool, let’s see what Delphi IDE offer in the feature Matrix :

As you can see, this is not cool for the professional Delphi customers. Ok I think these functions are totally essential when you are developing software in a Team or when you are project manager. But this is also cool when you are independent developer and you want to keep a watch on the quality of the code. I hate Embarcadero for this; they are giving you ersatz of softwares, ersatz of Intraweb, AQTime, FinalBuilder… Why they aren’t reduce the price of Delphi and give a total liberty for their users to buy the tools they need… I hate this! Haaaaaa! So what is the solution for analyzing our code? Buying an extension of Delphi for 1300 €! Not sure, you could get really more in buying Peganza Analyser for only 120 € (see coupon at the end). But this is not the exact same software! Peganza Pascal Analyser is far more complete than Delphi IDE cause it don’t give only metrics it gives you a lot of other things. The goal is not the same, so now I will stop to compare original tool include in Delphi and Peganza Analyser.

Review and tutorial of Peganza Pascal Analyser 5 :

 

To introduce and review this tool I will use the example of my software. After having setup my project and click Analysis-> Run!

Reports – General

Status: This report presents important facts about the current analysis, e.g. selected compiler directives and search paths.

Strong Warning: In this report you will see severe errors; they will often cause failures or erroneous results. (Property access in read/write methods or Ambiguous unit references). Sorry I haven’t this kind of problem in my software (It’s pretty good news), so no example. But sometimes it could happen if you are a bit dizzy !

Warning reports: It will give you some advises to improve your code:

Interfaced identifiers that are used, but not outside of unit (3, was 0):

TMailIMAPAccount = Class Type, Interfaced obj_mailaccount (98)

If I double click on the line, it opens me Delphi IDE and I see directly what the problem is.


// -----------------------

// TMailAccount  IMAP4

// -----------------------

TMailIMAPAccount = class(TMailAccount)

private

public

procedure Assign(Source: TObject); override;

end;

I don’t use this Class, but I wrote it to be use in a near future. So it’s a false positive :) ! When you have false positive you could delete them in adding

 //PALOFF 

Interfaced class identifiers that are public/published, but not used outside of unit (5, was 5):

————————————————————————————————

Colonnes : Array (static)      Property                listview_tools\TList_Colonne (61)


// Liste Colonne

TList_Colonne = class(TObjectList)

private

function GetColonne(Index: Integer): TColonne;

procedure SetColonne(Index: Integer; const Value: TColonne);

public

function NewOnlineColonne(TypeC: TColumnOnline; Position: Integer; Visible: Boolean; Size: Integer): TColonne_Online;

property Colonnes[index: integer]: TColonne read GetColonne write SetColonne; // PROBLEM HERE, the Class is public but not used...

end;

The problem is very simple to correct, the visibility of the property Colonnes is too high. The best way to correct it is to transfer it in private section.

Variables that are set, but never referenced (9, was 9):

—————————————————————————-

con_sasl_encours : tidsasl     ClassField              Thread_POP\Thread_POP3 (89)


Thread_POP3 = class(tthread)

private

FProcessName: string;

con_sasl_encours:   tidsasl; // What is the problem...

// FThread origine

FThread_IM: TIMThread;

//...

protected

// ...

public

// ...

end;

If I delete the con_sasl_encours, the program can’t compile. The only time con_sasl_encours is used it is for :

con_sasl_encours   := nil; 

So this object is totally useless, I can delete it. As you can see Peganza Analyser could help me to delete some objects totally useless. Maybe when I code it I had something in mind, but now, I dont know what it was… On my 22467 lines of code it is hard to find. Pascal Analyser could help you to clean your code.

Another one :

Variables that are set, but never referenced (8, was 9):

—————————————————————————-

Created : TDateTime            Var, Local              database_running\TDBB_RUN\Load_Main_Database (111)

 function TDBB_RUN.Load_Main_Database(const Path_BDD: String; const Ident: String): boolean;

var

Created: TDateTime;

begin

Created    := sqlite3_column_double(Stmt, 1);

//....

Created is a double that is never used ! It is set but never used. So I could delete it (or not if it is planned to be used in the future but this is not probable, I can’t remember a variable that is declared two years ago lool) !

I will not give you an example for ALL the reports in the Warning reports. But we have seen that this tab could really help use to find useless code, or strange code. Sometimes we do some very strange thing like:

for-loop variables read after loop (1, was 1):

—————————————————————————-

I : Integer                    Var, Local              Thread_POP\Thread_POP3\Execute\delete_mails (991)


try

for I := 0 to Liste_de_Mail.Count - 1 do

begin

// blablablblalaalal

end;

except

// Using of I

end;

This is an error from me, I was maybe drunk… The try except must be inside the loop and must be abort. So the code must be correct in :


for I := 0 to Liste_de_Mail.Count - 1 do

try

begin

// blablablblalaalal

except

Abort;

// Using of I

end;

end;

And the last one I would like to show you :

Functions called as procedures (37, was 37):

—————————————————————————-

configuration.sauvegarder_config at frm_principale (199)


procedure Tfrm_main.FormDestroy(Sender: TObject);

begin

sauvegarder_config;

// ....

end;

// The function

function sauvegarder_config: boolean;

begin

// ....

end;

As you can see, Pascal Analyser gives us a good way to find which part of the software is missing. When I developed Sauvegarder_Config it was designed to give true if the function works properly and false if there is a problem. So it’s totally useless to code a function if I don’t use the result and use it like a Procedure. Here PA could really improves my software if I use it correctly, I’m forced to consider the result of the function.

Optimization: By example the compiler of Delphi is optimized to work differently with constants and variables. So if you need speed and you are using variable for data which will not be modified it’s highly recommended to use constant instead. There are some other tricks to speed up your software. Pascal Analyser will help you to fix some leaks. Let’s see some examples:

Missing “const” for unmodified string parameter (3, was 3):

—————————————————————————-

BDD_Pass : String              ValParam                Thread_POP\Thread_POP3\Execute\Retrieve_Mails (594)

 // Procedure pour télécharger des mails

procedure Retrieve_Mails(BDD_Path: String; BDD_Pass: String);

var 

Here it’s not a variable that I would communicate to the function but a constant. This value will not be modified.

Array properties that are referenced/set within methods (1, was 0):

—————————————————————————-

Accounts : Array (static)      Property                obj_mailaccount\TList_MailAccount (123)

Referenced/set (1):

Assign                         Proc, Method            obj_mailaccount\TList_MailAccount (121)

For performance reasons it is faster to directly access the private array field. However, if the Get- or Set-method performs side effects, it makes sense to access the property.


// -----------------------

// TList_MailAccount

// -----------------------

TList_MailAccount = class(TObjectList)

private

function GetAccount(Index: integer): TMailAccount;

procedure SetAccount(Index: integer; const Value: TMailAccount);

public

procedure Assign(Source: TObject);

function NewPOPAccount: TMailPOPAccount;

property Accounts[index: integer]: TMailAccount read GetAccount write SetAccount;

end;

// Here Assign details

procedure TList_MailAccount.Assign(Source: TObject);

var //...

begin

//...

POPA.Assign(From.Accounts[I]); // THe problem is here

//...

end;

Must be change to


POPA.Assign(TMailPOPAccount(From.Items[I]));

And for the last example :

Local subprograms with references to outer local variables (6, was 6):

—————————————————————————-

GetIndex                       Proc, Local             frmpnl_show_offline_mail_\Tfrmpnl_show_offline_mail\offline_gridGetDisplText (368)


procedure Tfrmpnl_show_offline_mail.offline_gridGetDisplText(Sender: TObject; ACol, ARow: Integer; var Value: string);

var

Mail_Offline: TMail_Offline;

Index:        Integer;

procedure GetIndex;

begin

Index        := strtoint(offline_grid.AllCells[1, ARow]);

Mail_Offline := TMail_Offline(Data_Liste.Objets[Index].Data);

end;

Using some local variables in inner routines cost a bit CPU cause the compiler need to do special stacks manipulation.

I change it in :


procedure Tfrmpnl_show_offline_mail.offline_gridGetDisplText(Sender: TObject; ACol, ARow: Integer; var Value: string);

var

Mail_Offline: TMail_Offline;

procedure GetIndex(Mail: TMail_Offline);

var Index:Integer;

begin

Index        := strtoint(offline_grid.AllCells[1, ARow]);

Mail := TMail_Offline(Data_Liste.Objets[Index].Data);

end;

I’m not an expert on this subject, I hope this is not totally stupid. If someone could tell me if the solution is correct…

Memory:

It allows you to manage all the objects you are creating in the memory; Pascal Analyser could make some test. Like telling you if you are making unprotected calls to free (Use Finally end) on local or non-local object. It will also count number of Create and Free and tell you if there is something strange…

It’s you work to interpret all the reports ;)

Code Reduction:

This report pinpoints unnecessary code that could be deleted, resulting in a smaller amount of code to maintain and search for errors.

Convention Compliance/Inconsistent Case/Prefix:

When you are coding in Delphi, there is some convention (not exhaustive):

  • Like user-define type names start with the letter T (TForm_Tool), pointer by P, Exception by E…
  • Classfields must be declared in private section.
  • Get, Set exposed by properties (write/read).
  • Unsuitable names, numerals etc.
  • Not the same name for different identifiers.
  • Not too much long identifiers.

    Pascal Analyser gives you two other report one for inconsistent case (in fact when you are writing Buffer and bUFfer it is the same identifiers but it is most hard to read!). You could also detect which objects have not the right prefix.

    Reports – Metrics

    The next report is dedicated to Metrics. We have talk about this in the first part of this review/tutorial. The total metrics give you a rapid count of files, modules, lines and all kind of identifiers in Total/Local/Global/Interfaced/Unused. You could have this information for each module.

    Extract from the manual:

    1. Start with a value of 1 for the normal flow through a subprogram.
    2. Add 1 for each of these keywords: IF, WHILE, REPEAT, FOR, AND, OR, XOR, GOTO. Note that PAL always counts AND, OR, XOR, even if they are used as arithmetic operators in the actual code.
    3. Add 1 for each case label in a CASE statement. When the CASE does not have an ELSE, add 1 more.

    DP (Decision Point equivalent to McCabe’s metric) is a way to quantify the hardness to understand a function. If the subprogram or module has a DP > 10 it is a kind complex subprogram, with PA you could see easily what are the most hardcore to understand function. But sometimes you need to work with long function, which will give you a high DP. You can consider the result with DP/LOC (Lines of Code), if the DP/LOC is too high it is not good. After you need to see if the function is commented enough (if you have a high DP/LOC but a high Cmt(Comment)/LOC this is not a real problem, cause you are documenting enough your function (this is a subjective view).

    There is a lot of other statistics with metrics. The metrics here are not a lot, but enough to understand your program if you are self-developer.

    Let’s compare with Delphi Metrics  :

    This is really more complex and complete, I think this is not totally useful when your are independent developer. But if you are directing a project you will need more information, and this tool is great. But like every tool there are some limitations, by example in this particular situation Delphi Audits tell me that this code is never execute ! But this is an error, this code is always performed ! Sometimes just rewriting differently the code correct the problem.

    
    Synchronize( procedure begin
    
    // ...
    
    end);
    

    Personally I prefer Pascal Analyser. It’s more easy to find problem and to optimize my code. Pascal Analyser gives you also Object Oriented Metrics :

    • Weighted Methods per Class (WMC)
    • Depth of Inheritance Tree (DIT)
    • Number of children (NOC)
    • Coupling between Object Classes (CBO)
    • Response for a Class (RFC)
    • Loack of Cohesion in Methods (LCOM)

    With all these metrics, without directly watching the code, you could know if your code is great, just ok or really bad ! Just test the software and open the manual to learn more about these metrics.

    And a lot of other tools !

    Pascal Analyser comes with a lot of other tools. It could give you some infos about Modules, Identifiers, Duplicate Identifiers name (yes it’s not good to give the same name to different variables, most hard to read), similarity. This software could also list :

    • The Subprogram Index
    • Bindings
    • Third-party dependencies
    • Most called subprograms
    • Call Tree/ Reverse Call Tree/ Call Index
    • All the exceptions
    • All the todos
    • All the directives
    • All the conditional Symbols
    • The Brief Cross-reference
    • Interfaced identifiers that are used outside their units
    • And lof of other things !

    Just before conclusion, I will give a last function that I like a lot on this Analyser. In pascal you need to tell the compiler which files you want to include into your program with the uses, but sometimes you have some useless units in uses and it takes time to compiler to test if it useful or not. Here PA tells me directly which units I could delete easily. Example :

    Program ClientMail uses:

    Used units:

    sysutils in implementation

    ==> ExceptionLog unnecessary

    Forms in implementation

    dateutils in implementation

    frm_principale in implementation

    ==> memstreamini unnecessary

    ==> database unnecessary (has initialization)

    ==> ressourcestrings unnecessary (used by unit with init)

    ==> imail_type unnecessary

    ==> obj_mailaccount unnecessary

    ==> database_online unnecessary

    ==> chemins unnecessary

    ==> tools_strings unnecessary

    ==> constantes unnecessary

    ==> msgbox_tools unnecessary

    ==> database_cfg unnecessary

    ==> listview_tools unnecessary

    ==> configuration unnecessary

    frm_configuration in implementation

    ==> Thread_Manager unnecessary

    ==> database_mails unnecessary

    ==> database_maj unnecessary

    ==> frm_update_database unnecessary

    ==> load_skin unnecessary

    ==> combobox_tools unnecessary

    ==> database_running unnecessary

    ==> database_log unnecessary

    ==> obj_standard unnecessary

    ==> Thread_POP unnecessary

    ==> Interface_manager unnecessary

    ==> Treeview_tools unnecessary

    ==> menu_tools unnecessary

    ==> affichage unnecessary

    ==> frmpnl_log_ unnecessary

    ==> frmpnl_show_online_mail_ unnecessary

    ==> frmpnl_threads_ unnecessary

    ==> frmpnl_show_offline_mail_ unnecessary

    ==> crypt_decrypt unnecessary

    ==> frm_status unnecessary

    ==> reinit unnecessary

    frm_splashscreen in implementation

    ==> frm_lecture_mail unnecessary

    Conclusion !

    In conclusion this is a really valuable tool, you will save a lot of precious time if you maintain a high quality and reliable code. Maybe it will takes some hours to decrypt all the tools and use it correctly in your project (and correct some strange things), but after some times it will be automatic and you will do this naturally. You will write better code with less effort ! For me Pascal Analyser is a must have if you just have the professional version of Delphi.

    I have negotiated a reduction just for you, use the coupon code “PALBLOG” when ordering and you will get 10% of reduction.

    Click here to go to Peganza Website

     

    Reports – General

    Is Delphi dead ? (And why it’s not !)

    April 22nd, 2011 No comments

    Then

     

    Kaspersky protection softwares

     

    Delphi and C++ Builder IDE

     

    Fruity Loops audio producing tools

     

    The great installer InstallAware

     

    Audio library manager MediaMonkey

     

    are compiled by a ghost !

    How to prepare a connection to POP3 server with Indy TIdPOP3

    April 20th, 2011 No comments

    In this first post about Indy components, I will explain you how I prepare a connection to a POP3 Server. Indy components are a bit strange, sometimes buggy as Hell, sometimes very slow but this is also free components delivered with Delphi! I-Mail, my software is using Indy components, I have made several changes and discover some tricks and I would like to share my discovery with you.

    You could find the last development snapshot of Indy on this page, and SSL dll files on this page.
    The goal of this small piece of code is to prepare the connection for a future communication with a TIDPop3 account. It is explain how to use SSL/TLS, APOP, SASL mechanisms.

    function Thread_POP3.Prepare: boolean;
    var
      POP3Client:     TIdPOP3;
      con_SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
    begin
    
      result := true;
      try
        // All the pointer point to nothing in memory !
        con_sasl_anonymous := nil;
        con_sasl_md5       := nil;
        con_sasl_sh1       := nil;
        con_sasl_otp       := nil;
        con_sasl_login     := nil;
        con_sasl_plain     := nil;
        con_sasl_key       := nil;
        con_user_pass      := nil;
        con_SSLHandler     := nil;
        con_sasl_encours   := nil;
    
        // First thing to do is to create the Object
        POP3Client := TIdPOP3.Create(nil);
        // I want to receover the event status !
        POP3Client.OnStatus := POP3Status;
    
        // Do you want to use a secure connection ? Dont forget to add SSL library in the folder
        if Do_You_Want_SSL / TLS then
        begin
          con_SSLHandler       := TIdSSLIOHandlerSocketOpenSSL.Create(); // Creating the SSL Handler
          POP3Client.IOHandler := con_SSLHandler; // We want to use the SSLHandler
          POP3Client.UseTLS    := TIdUseTLS(0); // Here No SLL IOHandler (0)
          { TIdUseTLS = (
            utNoTLSSupport,
            utUseImplicitTLS, // ssl iohandler req, allways tls
            utUseRequireTLS, // ssl iohandler req, user command only accepted when in tls
            utUseExplicitTLS // < user can choose to use tls
            ); }
        end;
    
        // Now it's time to fill all the property needed for connection
        with POP3Client do
        begin
          AutoLogin      := false; // If you don't want to login when connect
          ConnectTimeout := 2500; // How much time before TimeOut
          Username       := FAccount.Username; // Username on the Server
          Password       := FAccount.Password; // Password on the Server
          Host           := FAccount.Serveur; // Host
          Port           := FAccount.Port; // Port
          AuthType       := TIdPOP3AuthenticationType(0); // how do you want to authentificate
          { TIdPOP3AuthenticationType = (patUserPass, patAPOP, patSASL); }
        end;
    
        // WARNING : FAccount is a specifi object in my software, you need to replace these values by yours.
    
        // If we are using SASL login
        if POP3Client.AuthType = patSASL then
        begin
    
          con_user_pass := TIdUserPassProvider.Create(nil); // Username and Paswword Login
    
          with con_user_pass do
          begin
            Username := FAccount.Username;
            Password := FAccount.Password;
          end;
    
          // What sort of SASL Mechanism ?
          case FAccount.Authent_SASL of
            SASLAnonymous:
              begin // Anonymous
                con_sasl_anonymous                 := TIdSASLAnonymous.Create(nil);
                POP3Client.SASLMechanisms.Add.SASL := tidsasl(con_sasl_anonymous);
              end;
    
            SASLCRAMMD5:
              begin // Cramm MD5
                con_sasl_md5                       := TIdSASLCRAMMD5.Create(nil);
                con_sasl_md5.UserPassProvider      := con_user_pass;
                POP3Client.SASLMechanisms.Add.SASL := tidsasl(con_sasl_md5);
              end;
    
            SASLCRAMSHA1:
              begin // Cramm SH1
                con_sasl_sh1                       := TIdSASLCRAMSHA1.Create(nil);
                con_sasl_sh1.UserPassProvider      := con_user_pass;
                POP3Client.SASLMechanisms.Add.SASL := tidsasl(con_sasl_sh1);
              end;
    
            SASLOTP:
              begin // SASL Otp
                con_sasl_otp                       := TIdSASLOTP.Create(nil);
                con_sasl_otp.UserPassProvider      := con_user_pass;
                POP3Client.SASLMechanisms.Add.SASL := tidsasl(con_sasl_otp);
              end;
    
            SASLLogin:
              begin // SASL Login
                con_sasl_login                     := TIdSASLLogin.Create(nil);
                con_sasl_login.UserPassProvider    := con_user_pass;
                POP3Client.SASLMechanisms.Add.SASL := tidsasl(con_sasl_login);
              end;
    
            SASLPlain:
              begin // SASL Plain
                con_sasl_plain                     := TIdSASLPlain.Create(nil);
                con_sasl_plain.UserPassProvider    := con_user_pass;
                con_sasl_plain.LoginAs             := FAccount.Authent_LoginAs;
                POP3Client.SASLMechanisms.Add.SASL := tidsasl(con_sasl_plain);
              end;
    
            SASLSKey:
              begin // SASL Key
                con_sasl_key                       := TIdSASLSKey.Create(nil);
                con_sasl_key.UserPassProvider      := con_user_pass;
                POP3Client.SASLMechanisms.Add.SASL := tidsasl(con_sasl_key);
              end;
          end;
    
        end;
      except
        result := false;
      end;
    end;
    


    See you next week for a new tutorial.

    L’Europe, Noir désir

    April 20th, 2011 No comments

     

     

    Les sangliers sont lachés
    Je répète :
    les sangliers sont lachés.

    Les petits patrons font les grandes rivières de diamant.
    Deux fois.

    Les roses de l’Europe sont le festin de Satan.
    Je répète :
    les roses de l’Europe sont le festin de Satan.

    Nous travaillons actuellement pour l’Europe. x4
    Voire pour le monde.

    Chère vieille Europe, cher vieux continent, putain autoritaire,
    aristocrate et libertaire, bourgeoise et ouvrière,
    pourpre et pomponnée de grands siècles et colosses titubants.
    Regarde tes épaules voûtées, pas moyen d’épousseter d’un seul geste,
    d’un seul, les vieilles pellicules, les peaux mortes d’hier et tabula rasa…
    D’ici on pourrait croire à de la pourriture noble et en suspention.
    il flotte encore dans l’air de cette odeur de soufre. Sale vieille Europe,
    celle qui entre deux guerres et même encore pendant caressait pour son bien
    le ventre des pays de ses lointains ailleurs et la bite à la main
    arrosait de son sperme les sexes autochtones.
    On se relève de ça ? On se relève de tout même des chutes sans fond.
    Nous avons su monter nous avons su descendre, nous pouvons arrêter
    et nous pouvons reprendre…
    Europe des lumières ou alors des ténèbres ;
    à peine des lucioles dans les théâtres d’ombre.
    A peine une étincelle dans la nuit qui s’installe et puis se ressaisit,
    et puis l’aube nouvelle, après les crimes d’enfance,
    les erreurs de jeunesse on n’arrache plus les ailes des libellules d’or.

    Nous travaillons actuellement pour l’Europe.
    Voire pour le monde.

    Amnistie, amnistie ou alors amnésie, qu’est-ce que vous volez que ça foute,
    de toutes façons il faut bien avancer, pressons le pas camarade
    et puis réalisons réalisons, il en restera toujours quelque chose allez !
    Matérialiste alors ça fait qu’au moins on est sûr de n’pas de tromper,
    et du tangible alors jusqu’à l’indigestion, du rationnel alors
    et jusqu’à en crever, des logiques implacables mais toujours pas de sens…
    Eh princesse de l’Histoire dans sa marche forcée,
    on finit par se perdre en passant sous tes arches multiséculaires.

    Voire pour le monde.
    Nous travaillons actuellement pour l’Europe.

    On est passé de tes arcanes passées, passé de tes arcanes passées,
    on est passé de tes arcanes passées, aux charmes technocrates…
    Alors l’Europe alors l’Europe alors l’Europe.
    Bruxelles, Schengen, Stasbourg, Maastricht, PIB, PIB, CEE, Euratom, OCDE et GATT.
    Protégez-nous marché de cet AMI commun d’un monde si petit.
    Euromonnaie unique, Nasdaq et CAC 40, orgiaque, idyllique, faites de la poésie,
    soutenez la culture, produisez du spectacle et de l’entertainment
    comme on dit chez nos frères d’Outre-Atlantique et toc anciens Européens,
    nouveaux maîtres du monde pendant que le dragon asiatique rêve, fait ses étirements,
    il est beau et puissant, crache du feu gentillement.
    Pendant qu’Ernest Antoine Seillière fait son apparition et nous déclare sa flamme
    il nous aime et nous dit :
    ” Nous ne sommes pas comme les politiques soumis à la pression de la rue. ”
    Et on entend au loin résonner les clameurs de la foule,
    les beaux mouvements d’ensemble, les défilés glorieux et puis la lutte des classes.
    Et maintenant c’est sérieux, eh bébé, c’est sérieux, on ne croit plus en rien,
    nous montons de toutes pièces ce buisness et Basta, on chevauche pas Pégase
    ça c’était pour l’extase c’est fini.
    Extension, expansion si possible, mais pas de rêve à porter seulement des dynamiques.
    D’abord la thune, bébé et le reste suivra et le reste viendra c’est ce qu’on dit
    je crois en cette époque là bénie des globophages.
    Chère vieille Europe, ta tête connaît à peine tes jambes qui souvent
    ne comprennent pas tes bras comment ça marche encore déjà.
    Comment ça marche un corps étranger à son corps on n’sait pas on s’en fout
    on s’embrasse quand même et puis on a raison.
    Sale vieille Europe, te souviens-tu de la force brutale, occident mal luné,
    guerre brûlante, guerre froide, et enfin de guerre lasse et enfin de guerre lasse.

    Nous travaillons actuellement pour l’Europe.

    En veux-tu en voilà des écoles de la performance et voilà des patrons
    créateurs du Global buisness dialogue ou Electronic commerce
    pour s’asseoir en gloussant sur toutes les exceptions à commencer
    par ce truc machin culturel.

    Histoires de producteurs et de consommateurs, du producteur au consommateur,
    du producteur au consommateur, et des intermédiaires à plus savoir qu’en foutre,
    toute ton âme s’est usée sur ce chemin sans fin et sur ce va et vient on y va,
    nous aussi, profiter, pas de raison, après tout ça ira,
    on n’en aura pour tout le monde, y’en aura pour tout le monde,
    on a dit pour tout le monde, pour tout le monde, pour tout l’monde et mon cul !

    A quelle hauteur vas-tu ériger tes remparts ?
    Où vas-tu repousser tes nouveaux murs d’enceinte ?

    Quelque chose est resté en travers de la gorge et nous voulons cracher
    c’est la moindre des choses mais vous pouvez, madame,
    vous adresser à nous car tout n’est pas perdu non tout n’est pas perdu
    de vos mythes d’aurore ici le soleil brille pour tous et on y croit.

    Nous travaillons actuellement pour l’Europe.
    Voire pour le monde.

    Quelque chose est resté en travers de la gorge et nous voulons cracher
    c’est la moindre des choses mais vous pouvez, madame,
    vous adresser à nous car tout n’est pas perdu non tout n’est pas perdu
    de vos mythes d’aurore ici le soleil brille pour tous et on y croit.

    La vérole sur vos gueules
    Je répète :
    la vérole sur vos gueules.
    Les soupirs de la sainte et les cris de la fée
    ne sont plus entendus au banquet des banquiers.
    Une fois.
    La marmite de l’ermite est remplie de rubis.
    Je répète :
    la marmite de l’ermite est remplie de rubis.

    La vieille Europe est la maquerelle des ballets roses.
    Deux fois.
    Quand les sirènes se taisent, les rapaces gueulent.
    Le rouge et le noir des tortures sont les fleurs du mal.
    Je répète :
    le rouge et le noir des tortures sont les fleurs du mal.

    Le jour de l’Occident est la nuit de l’Orient.
    Deux fois.
    Le jour de l’Occident est la nuit de l’Orient.

    Je ne suis pas chauvine mais la France est quand même la reine des fromages.
    Tryphon Tournesol est un zouave.
    Six fois.
    Le sang versé est la tasse de thé des géants de la foire.
    Deux fois.
    Il pleut des cordes sur la Concorde.
    Il pleut des cordes sur la Concorde.
    Les petites filles modèles sont les élues de l’Europe.
    Je répète :
    les petites filles modèles sont les élues de l’Europe.
    Merde à la sûreté.
    Deux fois.
    La folie des grandeurs tue les merles moqueurs.
    Je répète :
    la folie des grandeurs tue les merles moqueurs.
    Si vous ne trouvez plus rien cherchez autre chose.

    Paix en Suisse.
    Je répète :
    paix en Suisse.
    Les noces de sang incendient l’horizon.
    Deux fois.
    Le rimel de l’Europe coule sur les plastrons.
    Deux fois.

    La vie commence maintenant, et maintenant, et maintenant.

    L’Europe est une petite déesse mortelle.
    Deux fois.

    L’enfance de l’art est un lever de soleil.
    Je répète :
    l’enfance de l’art est un lever de soleil.

    Nous travaillons actuellement pour l’Europe…

     

    Noir désir, “Des visage des figures”, Bertrand Cantat, Brigitte Fontaine