<?xml version="1.0" encoding="ISO-8859-1"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Forum du club des développeurs et IT Pro - Blogs - ericb2</title>
		<link>https://www.developpez.net/forums/blogs/1525847-ericb2/</link>
		<description>Developpez.com, le Club des Développeurs et IT Pro</description>
		<language>fr</language>
		<lastBuildDate>Wed, 03 Jun 2026 08:50:35 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>15</ttl>
		<image>
			<url>https://forum.developpez.be/images/misc/rss.jpg</url>
			<title>Forum du club des développeurs et IT Pro - Blogs - ericb2</title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/</link>
		</image>
		<item>
			<title>Demande de stage : manque de visibilité de la rubrique ?</title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b10641/demande-stage-manque-visibilite-rubrique/</link>
			<pubDate>Fri, 11 Oct 2024 09:05:55 GMT</pubDate>
			<description>A-t-on vraiment besoin de...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore">A-t-on vraiment besoin de développeurs ?<br />
<br />
J'ai passé une annonce type &quot;Demande de stage&quot;  (bénévole !!), qui a été vue plus de 200 fois, mais ... rien.<br />
<br />
Manque de visibilité de la rubrique ou ... ?<br />
<br />
Lien : <a href="https://www.developpez.net/forums/d2170706/emploi-etudes-informatique/annonces-emplois/demandes/informatique-electronique-optique-recherche-stage-mission-l-industrie/" target="_blank">https://www.developpez.net/forums/d2...n-l-industrie/</a></blockquote>

]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b10641/demande-stage-manque-visibilite-rubrique/</guid>
		</item>
		<item>
			<title><![CDATA[Retour d'expérience Raspberry Pi 4 B (8Go de RAM) + ubuntu 20.10]]></title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b10015/retour-d-experience-raspberry-pi-4-b-8go-ram-p-ubuntu-20-10/</link>
			<pubDate>Mon, 08 Feb 2021 14:12:21 GMT</pubDate>
			<description><![CDATA[Pour un projet en cours, j'ai...]]></description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore">Pour un projet en cours, j'ai voulu tester le <b><font color="#0000FF">raspberry pi 4 (le modèle avec 8Go de RAM).</font></b> Comme je ne voulais pas oublier d'acheter un bidule ou un autre, j'ai acheté le <b><a href="http://www.hutopi.com/produit/mini-pc-switcher-raspberry-pi-4/" target="_blank"><font color="#0000FF"><b>kit Hutopi </b></font></a></b>(alimentation, boîtier fournis). Attention : je n'ai pas acheté ce kit en une fois,mais la machine finale, c'est ça :-) La machine que j'ai achetée vient en fait de <a href="https://www.pearl.fr/" target="_blank"><b><font color="#0000FF">Pearl</font></b></a> (Sélestat) parce que j'y passe de temps en temps (mais pour du handball ;-) ). Pour ce qui est de la distribution, <a href="https://cdimage.ubuntu.com/releases/20.10/release/" target="_blank"><font color="#0000FF"><b>Ubuntu propose une version aarch64</b></font></a> (choisissez l'archive &quot;preinstalled desktop image&quot;), alors je l'ai installée. <br />
<br />
<a href="https://www.reddit.com/r/linux/comments/lbu0t1/microsoft_repo_installed_on_all_raspberry_pis/" target="_blank"><font color="#FF0000"><b>Surtout n'installez pas la distribution de la fondation Raspberry Pi, car elle contient des choses douteuses venant de chez Microsoft, et qui sont installées à l'insu de votre plein gré.</b></font></a><br />
<br />
Pourquoi j'ai pris 8Go de RAM ?  Parce que je manipule plein d'images (montées en mémoire, pour des ralentis), et la RAM est utile (1280 x720 @24 images par seconde, avec <a href="https://github.com/opencv/opencv" target="_blank"><font color="#0000FF"><b>openCV</b></font></a>+ <a href="https://www.libsdl.org/" target="_blank"><b><font color="#0000FF">SDL2</font></b></a> + <a href="http://ffmpeg.org/" target="_blank"><b><font color="#0000FF">ffmpeg</font></b></a>). Si vous ne travaillez pas avec des vidéos, 4 Go fonctionne parfaitement, pas la peine de payer plus cher.<br />
<br />
<br />
En fait, après un rapide test, on se rend compte que cette machine n'est pas stable thermiquement, et j'ai finalement pris le temps d'acheter un boîtier <b><a href="https://www.kubii.fr/boitiers/3139-boitier-argon-one-m2-3272496304116.html" target="_blank"><font color="#0000FF">Argon One m.2</font></a></b> qui permet d'utiliser un disque dur SSD (<b>type  B + M  key, impératif</b>).<br />
<br />
<div style="text-align: center;"><img src="https://www.developpez.net/forums/attachments/p590419d1612790890/logiciels/microsoft-office/excel/macros-vba-excel/excel-publication-d-feuille-format-htm/boitier_argon_one_m.2.png/" border="0" alt="Nom : boitier_argon_one_m.2.png
Affichages : 31431
Taille : 48,0 Ko"  style="float: CONFIG" /></div><br />
Après ce second passage à la caisse, ça devient sérieux et vraiment correct : on peut faire des maths et pas mal de choses, y compris de la vidéo légère (enregistrement à 24 fps), visualisation en thermographie infrarouge (entre 17 et 25 fps) etc.<br />
<br />
<b>Le plus gros défaut : je n'ai pas encore réussi à faire passer la nappe pour la caméra NoIR</b>, et c'est vraiment un énorme défaut, mais je verrai plus tard si je trouve une vraie solution, car j'utilise des vraies caméra thermiques actuellement, et ça passe par le bus USB 3.0 (via la libuvc)<br />
<br />
<b>Autre défaut : le son</b>. Simplement merdique, qui passe par le hdmi (qui est un mauvais choix par excellence, puisque fermé, trappe à pognon et j'en passe, mais c'est l'interface vendue avec la machine, alors ...)<br />
<br />
Pour le reste, tout fonctionne. En particulier le wifi (rien à faire), et j'ai même compiz qui tourne sur le bureau (bon, ça chauffe un peu, mais c'est correct).<br />
<br />
Attention toutefois, si vous voulez que ça fonctionne bien, il faut installer mesa (version upstream avec git + meson + ninja) et la dernière version de DRM (Direct Rendering Manager) sur le <a href="https://gitlab.freedesktop.org/drm" target="_blank"><font color="#0000FF"><b>gitlab de FreeDesktop</b></font></a>. Sinon, ça ne marchera pas bien.<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td valign="top"><pre style="margin: 0">me@ma_machine:~$ glxinfo -B
name of display: :0.0
display: :0  screen: 0
direct rendering: Yes
Extended renderer info (GLX_MESA_query_renderer):
    Vendor: Broadcom (0x14e4)
    Device: V3D 4.2 (0xffffffff)
    Version: 20.3.3
    Accelerated: yes
    Video memory: 7630MB
    Unified memory: yes
    Preferred profile: core (0x1)
    Max core profile version: 3.0
    Max compat profile version: 3.0
    Max GLES1 profile version: 1.1
    Max GLES[23] profile version: 3.1
OpenGL vendor string: Broadcom
OpenGL renderer string: V3D 4.2
OpenGL version string: 3.0 Mesa 20.3.3 (git-124d611014)
OpenGL shading language version string: 1.30
OpenGL context flags: (none)

OpenGL ES profile version string: OpenGL ES 3.1 Mesa 20.3.3 (git-124d611014)
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10</pre></td></tr></table></pre>
</div><font color="#0000FF"><b>Important : pour que OpenGL (3.0) fonctionne, n'oubliez pas d'ajouter les lignes suivantes dans votre fichier ~/.bashrc</b></font> :<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:96px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br /></div></td><td valign="top"><pre style="margin: 0">
MESA_GLSL_VERSION_OVERRIDE=130
MESA_GL_VERSION_OVERRIDE=3.0

export MESA_GLSL_VERSION_OVERRIDE MESA_GL_VERSION_OVERRIDE</pre></td></tr></table></pre>
</div><br />
<a href="https://www.raspberrypi.org/blog/vc4-and-v3d-opengl-drivers-for-raspberry-pi-an-update/" target="_blank"><font color="#0000FF"><b>=&gt; pour en savoir plus sur V3D, et MESA sur Raspberry Pi</b></font> </a><br />
<br />
<b>Concernant la consommation, je dois être autour de 9W, avec un overclock CPU à 2GHz (stable) et un GPU à 650 MHz</b>. Ce n'est donc pas une machine puissante, mais ce n'est pas mon besoin actuel. <br />
<br />
À titre d'information, l'accélération matérielle, le décodage matériel pour la vidéo n'est PAS activée, mais après avoir réussi à compiler <b>Tizonia</b> (sans spotify), et plein d'autres choses, j'arrive à voir des vidéos en 720p @ 30 fps de façon tout à fait honorable.<br />
<br />
<br />
<br />
Pour avoir une idée des performances vidéo, je me suis fait quelques petits scripts, dont les résultats commencent à être encourageants. cf ci-dessous :<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br /></div></td><td valign="top"><pre style="margin: 0">me@ma_machine:~$ ./check_ffmpeg_codecs
 V..... libx264              libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (codec h264)
 V..... libx264rgb           libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 RGB (codec h264)
 V..... h264_omx             OpenMAX IL H.264 video encoder (codec h264)
 V..... h264_v4l2m2m         V4L2 mem2mem H.264 encoder wrapper (codec h264)
 V..... h264_vaapi           H.264/AVC (VAAPI) (codec h264)
 VFS..D h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
 V..... h264_v4l2m2m         V4L2 mem2mem H.264 decoder wrapper (codec h264)
 V.S... ffv1                 FFmpeg video codec #1
 VF.... ffvhuff              Huffyuv FFmpeg variant
 V.S... mpeg1video           MPEG-1 video
 V.S... mpeg2video           MPEG-2 video
 V..... mpeg2_vaapi          MPEG-2 (VAAPI) (codec mpeg2video)
 V.S... mpeg4                MPEG-4 part 2
 V..... libxvid              libxvidcore MPEG-4 part 2 (codec mpeg4)
 V..... mpeg4_omx            OpenMAX IL MPEG-4 video encoder (codec mpeg4)
 V..... mpeg4_v4l2m2m        V4L2 mem2mem MPEG4 encoder wrapper (codec mpeg4)
 V..... msmpeg4v2            MPEG-4 part 2 Microsoft variant version 2
 V..... msmpeg4              MPEG-4 part 2 Microsoft variant version 3 (codec msmpeg4v3)
 VFS..D ffv1                 FFmpeg video codec #1
 VF..BD ffvhuff              Huffyuv FFmpeg variant
 V.S.BD mpeg1video           MPEG-1 video
 V..... mpeg1_v4l2m2m        V4L2 mem2mem MPEG1 decoder wrapper (codec mpeg1video)
 V.S.BD mpeg2video           MPEG-2 video
 V.S.BD mpegvideo            MPEG-1 video (codec mpeg2video)
 V..... mpeg2_v4l2m2m        V4L2 mem2mem MPEG2 decoder wrapper (codec mpeg2video)
 VF..BD mpeg4                MPEG-4 part 2
 V..... mpeg4_v4l2m2m        V4L2 mem2mem MPEG4 decoder wrapper (codec mpeg4)
 V...BD msmpeg4v1            MPEG-4 part 2 Microsoft variant version 1
 V...BD msmpeg4v2            MPEG-4 part 2 Microsoft variant version 2
 V...BD msmpeg4              MPEG-4 part 2 Microsoft variant version 3 (codec msmpeg4v3)
 V..... libx265              libx265 H.265 / HEVC (codec hevc)
 V..... hevc_v4l2m2m         V4L2 mem2mem HEVC encoder wrapper (codec hevc)
 V..... hevc_vaapi           H.265/HEVC (VAAPI) (codec hevc)
 VFS..D hevc                 HEVC (High Efficiency Video Coding)
 V..... hevc_v4l2m2m         V4L2 mem2mem HEVC decoder wrapper (codec hevc)</pre></td></tr></table></pre>
</div><b><br />
[EDIT]</b> Pour ceux qui souhaiteraient comparer, voici deux petits scripts à tester dans un terminal :<br />
<br />
Script 1 : test des codecs (décodeurs et encodeurs) compilés avec ffmpeg. Me demander en privé si vous voulez savoir comment le l'ai compilé (il n'y a rien de compliqué en fait).<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:156px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td valign="top"><pre style="margin: 0">
#!/bin/bash

for i in h264 mpeg hevc h265
  do
    for j in encoders decoders
          do
            ffmpeg -hide_banner -${j} | grep ${i}
    done
done</pre></td></tr></table></pre>
</div>Plus un script supplémentaire : en utilisant vcgencmd (outil fermé, que Broadcom refuse de documenter) :<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:60px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br /></div></td><td valign="top"><pre style="margin: 0">
for codec in H264 MPG2 WVC1 MPG4 MJPG WMV9 ; do echo -e &quot;$codec:\t$(vcgencmd codec_enabled $codec)&quot; ; done</pre></td></tr></table></pre>
</div><br />
<b>Attention : je n'utilise PAS les obscures bibliothèques libomx* </b>(en 32 bits !) pour obtenir ces résultats. J'ai simplement pris le temps de compiler ce qu'il fallait, et de corriger ce qui devait l'être. Ce n'est pas trivial : débutants s'abstenir, simplement attendre que ce soit intégré dans votre distribution préférée.<br />
<br />
<br />
J'allais oublier : <a href="https://vulkan.lunarg.com/" target="_blank"><b><font color="#0000FF">Vulkan fonctionne aussi</font></b></a>.<br />
<br />
<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="40"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br />122<br />123<br />124<br />125<br />126<br />127<br />128<br />129<br />130<br />131<br />132<br />133<br />134<br />135<br />136<br />137<br />138<br />139<br />140<br />141<br />142<br />143<br />144<br />145<br />146<br />147<br />148<br />149<br />150<br />151<br />152<br />153<br />154<br />155<br />156<br />157<br />158<br />159<br />160<br />161<br />162<br />163<br />164<br />165<br />166<br />167<br />168<br />169<br />170<br />171<br />172<br />173<br />174<br />175<br />176<br />177<br />178<br />179<br />180<br />181<br />182<br />183<br />184<br />185<br />186<br />187<br />188<br />189<br />190<br />191<br />192<br />193<br />194<br />195<br />196<br />197<br />198<br />199<br />200<br />201<br />202<br />203<br />204<br />205<br />206<br />207<br />208<br />209<br />210<br />211<br />212<br />213<br />214<br />215<br />216<br />217<br />218<br />219<br />220<br />221<br />222<br />223<br />224<br />225<br />226<br />227<br />228<br />229<br />230<br />231<br />232<br />233<br />234<br />235<br />236<br />237<br />238<br />239<br />240<br />241<br />242<br />243<br />244<br />245<br />246<br />247<br />248<br />249<br />250<br />251<br />252<br />253<br />254<br />255<br />256<br />257<br />258<br />259<br />260<br />261<br />262<br />263<br />264<br />265<br />266<br />267<br />268<br />269<br />270<br />271<br />272<br />273<br />274<br />275<br />276<br />277<br />278<br />279<br />280<br />281<br />282<br />283<br />284<br />285<br />286<br />287<br />288<br />289<br />290<br />291<br />292<br />293<br />294<br />295<br />296<br />297<br />298<br />299<br />300<br />301<br />302<br />303<br />304<br />305<br />306<br />307<br />308<br />309<br />310<br />311<br />312<br />313<br />314<br />315<br />316<br />317<br />318<br />319<br />320<br />321<br />322<br />323<br />324<br />325<br />326<br />327<br />328<br />329<br />330<br />331<br />332<br />333<br />334<br />335<br />336<br />337<br />338<br />339<br />340<br />341<br />342<br />343<br />344<br />345<br />346<br />347<br />348<br />349<br />350<br />351<br />352<br />353<br />354<br />355<br />356<br />357<br />358<br />359<br />360<br />361<br />362<br />363<br />364<br />365<br />366<br />367<br />368<br />369<br />370<br />371<br />372<br />373<br />374<br />375<br />376<br />377<br />378<br />379<br />380<br />381<br />382<br />383<br />384<br />385<br />386<br />387<br />388<br />389<br />390<br />391<br />392<br />393<br />394<br />395<br />396<br />397<br />398<br />399<br />400<br />401<br />402<br />403<br />404<br />405<br />406<br />407<br />408<br />409<br />410<br />411<br />412<br />413<br /></div></td><td valign="top"><pre style="margin: 0">
me@ma_machine:~$ vulkaninfo 
WARNING: lavapipe is not a conformant vulkan implementation, testing use only.
==========
VULKANINFO
==========

Vulkan Instance Version: 1.2.141


Instance Extensions: count = 18
===============================
	VK_EXT_acquire_xlib_display            : extension revision 1
	VK_EXT_debug_report                    : extension revision 9
	VK_EXT_debug_utils                     : extension revision 2
	VK_EXT_direct_mode_display             : extension revision 1
	VK_EXT_display_surface_counter         : extension revision 1
	VK_KHR_device_group_creation           : extension revision 1
	VK_KHR_display                         : extension revision 23
	VK_KHR_external_fence_capabilities     : extension revision 1
	VK_KHR_external_memory_capabilities    : extension revision 1
	VK_KHR_external_semaphore_capabilities : extension revision 1
	VK_KHR_get_display_properties2         : extension revision 1
	VK_KHR_get_physical_device_properties2 : extension revision 1
	VK_KHR_get_surface_capabilities2       : extension revision 1
	VK_KHR_surface                         : extension revision 25
	VK_KHR_surface_protected_capabilities  : extension revision 1
	VK_KHR_wayland_surface                 : extension revision 6
	VK_KHR_xcb_surface                     : extension revision 6
	VK_KHR_xlib_surface                    : extension revision 6

Layers: count = 3
=================
VK_LAYER_KHRONOS_validation (Khronos Validation Layer) Vulkan version 1.2.141, layer version 1:
	Layer Extensions: count = 3
		VK_EXT_debug_report        : extension revision 9
		VK_EXT_debug_utils         : extension revision 1
		VK_EXT_validation_features : extension revision 2
	Devices: count = 1
		GPU id = 0 (llvmpipe (LLVM 11.0.0, 128 bits))
		Layer-Device Extensions: count = 3
			VK_EXT_debug_marker     : extension revision 4
			VK_EXT_tooling_info     : extension revision 1
			VK_EXT_validation_cache : extension revision 1

VK_LAYER_MESA_device_select (Linux device selection layer) Vulkan version 1.1.73, layer version 1:
	Layer Extensions: count = 0
	Devices: count = 1
		GPU id = 0 (llvmpipe (LLVM 11.0.0, 128 bits))
		Layer-Device Extensions: count = 0

VK_LAYER_MESA_overlay (Mesa Overlay layer) Vulkan version 1.1.73, layer version 1:
	Layer Extensions: count = 0
	Devices: count = 1
		GPU id = 0 (llvmpipe (LLVM 11.0.0, 128 bits))
		Layer-Device Extensions: count = 0

Presentable Surfaces:
=====================
GPU id : 0 (llvmpipe (LLVM 11.0.0, 128 bits)):
	Surface types: count = 2
		VK_KHR_xcb_surface
		VK_KHR_xlib_surface
	Formats: count = 2
		SurfaceFormat[0]:
			format = FORMAT_B8G8R8A8_SRGB
			colorSpace = COLOR_SPACE_SRGB_NONLINEAR_KHR
		SurfaceFormat[1]:
			format = FORMAT_B8G8R8A8_UNORM
			colorSpace = COLOR_SPACE_SRGB_NONLINEAR_KHR
	Present Modes: count = 4
		PRESENT_MODE_IMMEDIATE_KHR
		PRESENT_MODE_MAILBOX_KHR
		PRESENT_MODE_FIFO_KHR
		PRESENT_MODE_FIFO_RELAXED_KHR
	VkSurfaceCapabilitiesKHR:
	-------------------------
		minImageCount       = 3
		maxImageCount       = 0
		currentExtent:
			width  = 256
			height = 256
		minImageExtent:
			width  = 256
			height = 256
		maxImageExtent:
			width  = 256
			height = 256
		maxImageArrayLayers = 1
		supportedTransforms: count = 1
			SURFACE_TRANSFORM_IDENTITY_BIT_KHR
		currentTransform    = SURFACE_TRANSFORM_IDENTITY_BIT_KHR
		supportedCompositeAlpha: count = 2
			COMPOSITE_ALPHA_OPAQUE_BIT_KHR
			COMPOSITE_ALPHA_INHERIT_BIT_KHR
		supportedUsageFlags: count = 5
			IMAGE_USAGE_TRANSFER_SRC_BIT
			IMAGE_USAGE_TRANSFER_DST_BIT
			IMAGE_USAGE_SAMPLED_BIT
			IMAGE_USAGE_STORAGE_BIT
			IMAGE_USAGE_COLOR_ATTACHMENT_BIT
	VkSurfaceCapabilities2EXT:
	--------------------------
		supportedSurfaceCounters: count = 0
			None
	VkSurfaceProtectedCapabilitiesKHR:
	----------------------------------
		supportsProtected = false



Device Groups:
==============
Group 0:
	Properties:
		physicalDevices: count = 1
			llvmpipe (LLVM 11.0.0, 128 bits) (ID: 0)
		subsetAllocation = 0

	Present Capabilities = Group does not support VK_KHR_device_group, skipping printing present capabilities


Device Properties and Extensions:
=================================
GPU0:
VkPhysicalDeviceProperties:
---------------------------
	apiVersion     = 4194306 (1.0.2)
	driverVersion  = 1 (0x0001)
	vendorID       = 0x10005
	deviceID       = 0x0000
	deviceType     = PHYSICAL_DEVICE_TYPE_CPU
	deviceName     = llvmpipe (LLVM 11.0.0, 128 bits)

VkPhysicalDeviceLimits:
-----------------------
	maxImageDimension1D                             = 16384
	maxImageDimension2D                             = 16384
	maxImageDimension3D                             = 4096
	maxImageDimensionCube                           = 32768
	maxImageArrayLayers                             = 2048
	maxTexelBufferElements                          = 134217728
	maxUniformBufferRange                           = 65536
	maxStorageBufferRange                           = 134217728
	maxPushConstantsSize                            = 128
	maxMemoryAllocationCount                        = 4096
	maxSamplerAllocationCount                       = 32768
	bufferImageGranularity                          = 0x00000040
	sparseAddressSpaceSize                          = 0x00000000
	maxBoundDescriptorSets                          = 8
	maxPerStageDescriptorSamplers                   = 32
	maxPerStageDescriptorUniformBuffers             = 16
	maxPerStageDescriptorStorageBuffers             = 16
	maxPerStageDescriptorSampledImages              = 128
	maxPerStageDescriptorStorageImages              = 128
	maxPerStageDescriptorInputAttachments           = 8
	maxPerStageResources                            = 128
	maxDescriptorSetSamplers                        = 32768
	maxDescriptorSetUniformBuffers                  = 256
	maxDescriptorSetUniformBuffersDynamic           = 256
	maxDescriptorSetStorageBuffers                  = 256
	maxDescriptorSetStorageBuffersDynamic           = 256
	maxDescriptorSetSampledImages                   = 256
	maxDescriptorSetStorageImages                   = 256
	maxDescriptorSetInputAttachments                = 256
	maxVertexInputAttributes                        = 32
	maxVertexInputBindings                          = 32
	maxVertexInputAttributeOffset                   = 2047
	maxVertexInputBindingStride                     = 2048
	maxVertexOutputComponents                       = 128
	maxTessellationGenerationLevel                  = 64
	maxTessellationPatchSize                        = 32
	maxTessellationControlPerVertexInputComponents  = 128
	maxTessellationControlPerVertexOutputComponents = 128
	maxTessellationControlPerPatchOutputComponents  = 128
	maxTessellationControlTotalOutputComponents     = 4096
	maxTessellationEvaluationInputComponents        = 128
	maxTessellationEvaluationOutputComponents       = 128
	maxGeometryShaderInvocations                    = 32
	maxGeometryInputComponents                      = 64
	maxGeometryOutputComponents                     = 128
	maxGeometryOutputVertices                       = 1024
	maxGeometryTotalOutputComponents                = 1024
	maxFragmentInputComponents                      = 128
	maxFragmentOutputAttachments                    = 8
	maxFragmentDualSrcAttachments                   = 2
	maxFragmentCombinedOutputResources              = 8
	maxComputeSharedMemorySize                      = 32768
	maxComputeWorkGroupCount: count = 3
		65535
		65535
		65535
	maxComputeWorkGroupInvocations                  = 1024
	maxComputeWorkGroupSize: count = 3
		1024
		1024
		1024
	subPixelPrecisionBits                           = 8
	subTexelPrecisionBits                           = 8
	mipmapPrecisionBits                             = 8
	maxDrawIndexedIndexValue                        = 4294967295
	maxDrawIndirectCount                            = 4294967295
	maxSamplerLodBias                               = 16
	maxSamplerAnisotropy                            = 16
	maxViewports                                    = 16
	maxViewportDimensions: count = 2
		16384
		16384
	viewportBoundsRange: count = 2
		-32768
		32768
	viewportSubPixelBits                            = 0
	minMemoryMapAlignment                           = 4096
	minTexelBufferOffsetAlignment                   = 0x00000010
	minUniformBufferOffsetAlignment                 = 0x00000010
	minStorageBufferOffsetAlignment                 = 0x00000010
	minTexelOffset                                  = -32
	maxTexelOffset                                  = 31
	minTexelGatherOffset                            = -32
	maxTexelGatherOffset                            = 31
	minInterpolationOffset                          = -2
	maxInterpolationOffset                          = 2
	subPixelInterpolationOffsetBits                 = 8
	maxFramebufferWidth                             = 16384
	maxFramebufferHeight                            = 16384
	maxFramebufferLayers                            = 2048
	framebufferColorSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	framebufferDepthSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	framebufferStencilSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	framebufferNoAttachmentsSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	maxColorAttachments                             = 8
	sampledImageColorSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	sampledImageIntegerSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	sampledImageDepthSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	sampledImageStencilSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	storageImageSampleCounts: count = 2
		SAMPLE_COUNT_1_BIT
		SAMPLE_COUNT_4_BIT
	maxSampleMaskWords                              = 1
	timestampComputeAndGraphics                     = true
	timestampPeriod                                 = 1
	maxClipDistances                                = 8
	maxCullDistances                                = 8
	maxCombinedClipAndCullDistances                 = 8
	discreteQueuePriorities                         = 2
	pointSizeRange: count = 2
		0
		255
	lineWidthRange: count = 2
		1
		1
	pointSizeGranularity                            = 0.125
	lineWidthGranularity                            = 0
	strictLines                                     = false
	standardSampleLocations                         = true
	optimalBufferCopyOffsetAlignment                = 0x00000080
	optimalBufferCopyRowPitchAlignment              = 0x00000080
	nonCoherentAtomSize                             = 0x00000040

VkPhysicalDeviceSparseProperties:
---------------------------------
	residencyStandard2DBlockShape            = false
	residencyStandard2DMultisampleBlockShape = false
	residencyStandard3DBlockShape            = false
	residencyAlignedMipSize                  = false
	residencyNonResidentStrict               = false

VkPhysicalDeviceDriverPropertiesKHR:
------------------------------------
	driverID           = DRIVER_ID_MESA_LLVMPIPE
	driverName         = llvmpipe
	driverInfo         = Mesa 20.3.3 (git-124d611014) (LLVM 11.0.0)
	conformanceVersion = 1.0.0.0

VkPhysicalDeviceIDPropertiesKHR:
--------------------------------
	deviceUUID      = 00000000-0000-0000-0000-000000000000
	driverUUID      = 00000000-0000-0000-0000-000000000000
	deviceNodeMask  = 0
	deviceLUIDValid = false


Device Extensions: count = 14
-----------------------------
	VK_EXT_external_memory_dma_buf      : extension revision 1
	VK_EXT_private_data                 : extension revision 1
	VK_GOOGLE_decorate_string           : extension revision 1
	VK_GOOGLE_hlsl_functionality1       : extension revision 1
	VK_KHR_bind_memory2                 : extension revision 1
	VK_KHR_dedicated_allocation         : extension revision 1
	VK_KHR_driver_properties            : extension revision 1
	VK_KHR_get_memory_requirements2     : extension revision 1
	VK_KHR_incremental_present          : extension revision 1
	VK_KHR_maintenance1                 : extension revision 1
	VK_KHR_relaxed_block_layout         : extension revision 1
	VK_KHR_sampler_mirror_clamp_to_edge : extension revision 1
	VK_KHR_storage_buffer_storage_class : extension revision 1
	VK_KHR_swapchain                    : extension revision 68

VkQueueFamilyProperties:
========================
	queueProperties[0]:
	-------------------
		minImageTransferGranularity = (1,1,1)
		queueCount                  = 1
		queueFlags                  = QUEUE_GRAPHICS | QUEUE_COMPUTE | QUEUE_TRANSFER
		timestampValidBits          = 64
		present support             = true

VkPhysicalDeviceMemoryProperties:
=================================
memoryHeaps: count = 1
	memoryHeaps[0]:
		size   = 2147483648 (0x80000000) (2.00 GiB)
		budget = 255 (0x000000ff) (255.00 B)
		usage  = 255 (0x000000ff) (255.00 B)
		flags: count = 1
			MEMORY_HEAP_DEVICE_LOCAL_BIT
memoryTypes: count = 1
	memoryTypes[0]:
		heapIndex     = 0
		propertyFlags = 0x000f: count = 4
			MEMORY_PROPERTY_DEVICE_LOCAL_BIT
			MEMORY_PROPERTY_HOST_VISIBLE_BIT
			MEMORY_PROPERTY_HOST_COHERENT_BIT
			MEMORY_PROPERTY_HOST_CACHED_BIT
		usable for:
			IMAGE_TILING_OPTIMAL:
				color images
				FORMAT_D16_UNORM
				FORMAT_X8_D24_UNORM_PACK32
				FORMAT_D32_SFLOAT
				FORMAT_S8_UINT
				FORMAT_D24_UNORM_S8_UINT
				FORMAT_D32_SFLOAT_S8_UINT
				(non-sparse)
			IMAGE_TILING_LINEAR:
				color images
				(non-sparse)

VkPhysicalDeviceFeatures:
=========================
	robustBufferAccess                      = true
	fullDrawIndexUint32                     = true
	imageCubeArray                          = true
	independentBlend                        = true
	geometryShader                          = true
	tessellationShader                      = true
	sampleRateShading                       = true
	dualSrcBlend                            = true
	logicOp                                 = true
	multiDrawIndirect                       = true
	drawIndirectFirstInstance               = true
	depthClamp                              = true
	depthBiasClamp                          = true
	fillModeNonSolid                        = true
	depthBounds                             = false
	wideLines                               = false
	largePoints                             = true
	alphaToOne                              = true
	multiViewport                           = true
	samplerAnisotropy                       = false
	textureCompressionETC2                  = false
	textureCompressionASTC_LDR              = false
	textureCompressionBC                    = true
	occlusionQueryPrecise                   = true
	pipelineStatisticsQuery                 = true
	vertexPipelineStoresAndAtomics          = true
	fragmentStoresAndAtomics                = true
	shaderTessellationAndGeometryPointSize  = true
	shaderImageGatherExtended               = true
	shaderStorageImageExtendedFormats       = false
	shaderStorageImageMultisample           = true
	shaderStorageImageReadWithoutFormat     = false
	shaderStorageImageWriteWithoutFormat    = true
	shaderUniformBufferArrayDynamicIndexing = false
	shaderSampledImageArrayDynamicIndexing  = false
	shaderStorageBufferArrayDynamicIndexing = false
	shaderStorageImageArrayDynamicIndexing  = false
	shaderClipDistance                      = true
	shaderCullDistance                      = true
	shaderFloat64                           = true
	shaderInt64                             = true
	shaderInt16                             = true
	shaderResourceResidency                 = false
	shaderResourceMinLod                    = false
	sparseBinding                           = false
	sparseResidencyBuffer                   = false
	sparseResidencyImage2D                  = false
	sparseResidencyImage3D                  = false
	sparseResidency2Samples                 = false
	sparseResidency4Samples                 = false
	sparseResidency8Samples                 = false
	sparseResidency16Samples                = false
	sparseResidencyAliased                  = false
	variableMultisampleRate                 = false
	inheritedQueries                        = false</pre></td></tr></table></pre>
</div><b><font color="#0000FF">À suivre.</font></b><br />
<br />
<b>Eric Bachard  02/2021</b></blockquote>

]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b10015/retour-d-experience-raspberry-pi-4-b-8go-ram-p-ubuntu-20-10/</guid>
		</item>
		<item>
			<title><![CDATA[[Linux] Ressource : petite API pour s'enregistrer sous Linux]]></title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b9794/linux-ressource-petite-api-s-enregistrer-sous-linux/</link>
			<pubDate>Fri, 11 Sep 2020 11:34:20 GMT</pubDate>
			<description>---Citation (Envoyé par...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore"><div class="bbcode_container">
	<div class="bbcode_quote">
		<div class="quote_container">
			<div class="bbcode_quote_container"></div>
			
				<div class="bbcode_postedby">
					<img src="https://forum.developpez.be/images/misc/quote_icon.png" alt="Citation" /> Envoyé par <strong>ericb2</strong>
					<a href="showthread.php?p=11616705#post11616705" rel="nofollow"><img class="inlineimg" src="https://forum.developpez.be/images/buttons/viewpost-right.png" alt="Voir le message" /></a>
				</div>
				<div class="message"><font color="#FF0000"><b>Attention : LINUX seulement (je ne sais pas encore quoi faire pour Windows, mais ça viendra)</b></font><br />
<br />
Bonjour,<br />
<br />
Pour ceux que cela intéresse, j'ai écrit une <b><font color="#0000FF">petite application en C++ </font></b>permettant de s'enregistrer (micro interne ou webcam) via alsa + pulse sous Linux (c'est souvent installé par défaut sous Linuxmint). Tout est <a href="https://github.com/ebachard/Linux_Alsa_Audio_Record" target="_blank"> <b><font color="#0000FF">ICI</font></b></a><br />
<br />
<b>La seule dépendance est la libasound2 </b>:<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:144px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td valign="top"><pre style="margin: 0">$apt-cache search asound | grep libasound2

libasound2 - bibliothèque partagée pour les applications ALSA
libasound2-data - Fichiers de configuration et profils pour les pilotes ALSA
libasound2-dev - bibliothèque partagée pour les applications ALSA -- fichiers de développement
libasound2-doc - Documentation pour la programmation d'applications ALSA en espace utilisateur
libasound2-plugins - Plugins additionnels pour la bibliothèque ALSA

(quelques d'autres)</pre></td></tr></table></pre>
</div><b>Pour installer la bonne bibliothèque</b> :<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:60px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br /></div></td><td valign="top"><pre style="margin: 0">
sudo apt-get install libasound2 libasound2-dev</pre></td></tr></table></pre>
</div><b>Et ça devrait le faire :-)</b><br />
<br />
<br />
Si vous voulez intégrer cette fonctionnalité dans votre logiciel, un exemple d'intégration est inclus dans les sources, mais quelquefois, c'est mieux de voir ce que ça donne en mode graphique et vous pouvez vous inspirer de l'exemple que j'ai donné dans <a href="https://framagit.org/ericb/miniDart" target="_blank"><b><font color="#0000FF">miniDart</font></b></a>,un autre logiciel que j'écris.<br />
<br />
<b><font color="#0000FF">Méthode</font></b> : <br />
<br />
ajouter <a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/inc/alsa_recorder.hpp" target="_blank"><b><font color="#0000FF">alsarecorder.hpp</font></b></a> qu'on utilisera avec un #include &quot;alsa_recorder.hpp&quot;<br />
<br />
Pour l'implémentation, il faudra ajouter <a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/src/Audio/alsa_recorder.cpp" target="_blank"><b><font color="#0000FF">alsa_recorder.cpp</font></b></a>  dans vos sources.<br />
<br />
<b>Pour l'utilisation :</b><br />
<br />
Ajouter le fichier d'en-tête permettant de définir l'interface :<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:96px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br /></div></td><td valign="top"><pre style="margin: 0">
#ifdef __LINUX
#include &quot;alsa_recorder.hpp&quot;
#include &lt;thread&gt;
#endif</pre></td></tr></table></pre>
</div><b>Une fonction statique pour lancer l'enregistrement (parce que j'utilise std::thread, mais il doit y avoir une astuce pour faire autrement)</b> :<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:60px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br /></div></td><td valign="top"><pre style="margin: 0">
static void start_audio_recording(AlsaRecorder * p_aRec);</pre></td></tr></table></pre>
</div><b>Son implémentation aussi  :</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td valign="top"><pre style="margin: 0">static void start_audio_recording(AlsaRecorder * p_aRec)
{
    //fname = filename;
    //std::cerr &lt;&lt; &quot;fname : &quot; &lt;&lt; fname &lt;&lt; &quot;\n&quot;;
    p_aRec-&gt;set_sound_device(&quot;default&quot;);
    p_aRec-&gt;init();

    int anErr = p_aRec-&gt;do_record();

    if (anErr !=  EXIT_SUCCESS)
        std::cout &lt;&lt; &quot;Pb with do_record() &quot;  &lt;&lt; &quot;\n&quot;;

    std::cout &lt;&lt; &quot;Close wave file&quot; &lt;&lt; &quot;\n&quot;;
    p_aRec-&gt;close_wav_file();

    std::cout &lt;&lt; &quot;Close default soundcard&quot; &lt;&lt; &quot;\n&quot;;
    p_aRec-&gt;close_soundcard();
}</pre></td></tr></table></pre>
</div><br />
<br />
<br />
<br />
<b>Dans la fonction principale, création d'une instance d'un objet de type AlsaRecorder</b> (et d'un pointeur associé, plus pratique)<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">
    AlsaRecorder aRec;
    AlsaRecorder * p_aRec = &amp;aRec;</pre></td></tr></table></pre>
</div>Enfin, si on appuie sur le bouton (rappel : ImGui fonctionne en mode immédiat)<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br /></div></td><td valign="top"><pre style="margin: 0">
                    if ((b_recording_checked) &amp;&amp; (!b_recording_video))                           /// on vient d'appuyer sur le bouton &quot;Enregistrer&quot; ET on n'était pas en train d'enregistrer
                    {
                        if (strlen(defaultPath) == 0)
                        {
                            // open modal dialog : il faut définir un répertoire de travail
                            // dans lequel seront enregistrées les images
                            ImGui::OpenPopup(CURRENT_WORKING_DIRECTORY_POPUP);
                            if( ImGui::BeginPopupModal(CURRENT_WORKING_DIRECTORY_POPUP, NULL, ImGuiWindowFlags_AlwaysAutoResize))
                            {
                                ImGui::Text(HELP_CHOOSE_WORKING_REC_DIRECTORY);
                                ImGui::NewLine();

                                ImGui::Spacing(); ImGui::SameLine();
                                if (ImGui::Button(OK_BUTTON, ImVec2(120,0)))
                                {
                                    b_recording_checked = false;
                                    selectFolder(currentPath);
                                    ImGui::CloseCurrentPopup();
                                }
                                ImGui::EndPopup();
                            }
                        }
                        else
                        {
                            b_recording_video = true;
                            b_draw_recording_info = true;
                            b_startNewRecording = true;
                            std::cout &lt;&lt; &quot;Enregistrement en cours&quot; &lt;&lt; &quot;\n&quot;;
                            inc_color();

                            p_aRec-&gt;set_quit(false);                                    // On vient d'appuyer sur &quot;Enregistrer&quot;

                            first = std::thread(*start_audio_recording, p_aRec);   // on lance le fil d'exécution en parallèle (enregistrement SON seulement ici)

                        }
                    }
                    else if ((!b_recording_checked) &amp;&amp; (b_recording_video))  // on vient d'appuyer sur &quot;Arrêter l'enregistrement&quot;
                    {
                        b_recording_video = false;
                        b_draw_recording_info = false;

                        // stop audio recording
                        p_aRec-&gt;set_quit(true);      ///  Le booléen passe à VRAI =&gt; on arrête l'enregistrement
                        first.join();                         /// on termine le thread  

                        oVideoWriter.release();
                        std::cout &lt;&lt; &quot;Fin d'enregistrement&quot; &lt;&lt; &quot;\n&quot;;
                    }</pre></td></tr></table></pre>
</div><br />
<b><font color="#0000FF">À la fin,vous obtenez un fichier .wav, mais j'ai proposé un script pour le convertir en mp3 sur github, pour ceux qui le souhaitent.<br />
<br />
Merci d'avance pour tout retour constructif, toute aide ou même toute contribution (soyons fous ! )</font></b></div>
			
		</div>
	</div>
</div></blockquote>

]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b9794/linux-ressource-petite-api-s-enregistrer-sous-linux/</guid>
		</item>
		<item>
			<title><![CDATA[Écriture d'un canvas en C++, avec Dear ImGui (PARTIE 2 sur 8)]]></title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b9784/ecriture-d-canvas-cpp-dear-imgui-partie-2-8/</link>
			<pubDate>Thu, 03 Sep 2020 17:06:24 GMT</pubDate>
			<description>*Partie 2.  La classe canvas...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore"><div style="text-align: center;"><b><font size="4">Partie 2.  La classe canvas (amélioration et tests)</font></b></div><br />
<b><font size="3">Le contexte</font> </b><br />
<br />
La classe <b><font color="#0000FF">Canvas</font></b> a été créée pour fonctionner avec le logiciel <font color="#0000FF"><b><a href="https://framagit.org/ericb/miniDart" target="_blank">miniDart</a></b></font>, mais on devrait pouvoir l'adapter à un autre logiciel sans problème. Celui-ci  est basé sur <font color="#0000FF"><b><a href="https://github.com/ocornut/imgui" target="_blank">Dear ImGui</a></b></font>, et fonctionne selon le paradigme du mode immédiat <br />
<br />
Historiquement, et pour ceux qui l'ont vue, le mode immédiat, c'est la vidéo de <font color="#0000FF"><b>Casey Muratori</b></font>:<br />
<br />
<div style="text-align: center;"> 
<div class="video-container"><iframe class="restrain" title="YouTube video player" width="560" height="315" allowfullscreen src="//www.youtube.com/embed/Z1qyvQsjK5Y?wmode=transparent&amp;fs=1" frameborder="0"></iframe></div>
.</div><br />
Mais il y a eu d'autres présentations et définitions, comme par exemple celle de <font color="#0000FF"><b><a href="http://sol.gfxile.net/imgui/" target="_blank">Jari Komppa </a></b></font> que je trouve d'une merveilleuse simplicité. À propos de <font color="#0000FF"><b>Jari Komppa</b></font>, allez aussi voir le projet <b><font color="#0000FF"><a href="https://github.com/jarikomppa/soloud" target="_blank">SoLoud</a> </font></b>qui est assez incroyable lui aussi.<br />
<br />
Plus simplement, le logiciel <font color="#0000FF"><b><a href="https://framagit.org/ericb/miniDart" target="_blank">miniDart</a></b></font> fonctionne comme un moteur de jeu : on exécute une boucle infinie de type &quot;évènements, mise à jour des états logiques<br />
puis calcul du rendu graphique et affichage&quot;, et on recommence indéfiniment dans que la condition de sortie de la boucle n'est pas réalisée.<br />
<br />
Important: on n'effectue l'étape du rendu+affichage qu'une fois dans la boucle. Chaque nouvel objet est ajouté dans une pile qui n'est vidée qu'une seule fois par tour lors du rendu, afin d'éviter de surcharger la machine (cf  le fonctionnement de Dear ImGui).<br />
<br />
Dans <font color="#0000FF"><b><a href="https://framagit.org/ericb/miniDart" target="_blank">miniDart</a></b></font>, pour éviter de passer d'une fenêtre à une autre, on utilise des onglets. Un seul onglet est actif à la fois, le reste ne sera ni évalué, ni calculé dans la boucle (on ne dépensera pas de ressources pour &quot;afficher&quot; les objets contenus dans les onglets inactifs, mais les instances des objets créés sont toujours en mémoire). Cela signifie aussi que l'on pourra avoir plusieurs instances de ce Canvas fonctionnant en même temps, mais ce sera forcément une unique instance par onglet.<br />
<br />
En ce qui concerne le <font color="#0000FF"><b>Canvas</b></font>, il <b>NE</b> devra être exécuté et accessible à l'utilisateur <b>QUE SI</b> :<br />
<br />
- l'onglet dans lequel une instance existe est actif;<br />
- cette instance a correctement été initialisée ;<br />
- la barre d'outils est active. Validation : on voit les icônes des objets pouvant être dessinés ;<br />
<br />
<br />
<img src="https://www.developpez.net/forums/attachments/p578423d1599119381/c-cpp/c/cgi-c/canvas_inactif.png/" border="0" alt="Nom : canvas_inactif.png
Affichages : 14273
Taille : 55,0 Ko"  style="float: CONFIG" /><br />
<br />
<b><div style="text-align: center;">Canvas inactif : on ne peut pas dessiner</div></b><br />
<br />
<br />
<img src="https://www.developpez.net/forums/attachments/p578424d1599119422/c-cpp/c/cgi-c/canvas_actif.png/" border="0" alt="Nom : canvas_actif.png
Affichages : 6988
Taille : 504,7 Ko"  style="float: CONFIG" /><br />
<br />
<b><div style="text-align: center;">Canvas actif : on peut sélectionner un objet, et le dessiner dans la zone  juste au dessus (celle contenant l'image)</div></b><br />
<br />
- les objets peuvent être dessinés seulement la zone dans laquelle des images sont affichées, y compris sans qu'on visualise quelque chose (pas de source vidéo active)<br />
<br />
- le curseur de la souris survole une certaine partie de l'écran. Validation : l'objet dessiné change de couleur lorsqu'il est survolé par le curseur de la souris<br />
<br />
<b>Objet non survolé</b> :    <div style="text-align: center;"><img src="https://www.developpez.net/forums/attachments/p578428d1599120780/c-cpp/c/cgi-c/objet_non_survole.png/" border="0" alt="Nom : objet_non_survole.png
Affichages : 6530
Taille : 22,9 Ko"  style="float: CONFIG" /></div><br />
Remarque : noter la couleur grise de l'objet survolé par le curseur de la souris ci-dessous (TODO : trouver une plus belle couleur  :-) )<br />
<br />
<b>Objet survolé </b>: <div style="text-align: center;"> <img src="https://www.developpez.net/forums/attachments/p578429d1599120826/c-cpp/c/cgi-c/objet_survole.png/" border="0" alt="Nom : objet_survole.png
Affichages : 6566
Taille : 68,2 Ko"  style="float: CONFIG" /><br />
</div>- [TODO, à venir ultérieurement] les objets dessinés devront pouvoir être intégrés dans les images pendant l'enregistrement<br />
<br />
<br />
<u>Remarque</u> :  actuellement, <b><a href="https://github.com/opencv/opencv" target="_blank">OpenCV</a></b> affiche des images dans une vue openGL, et OpenGL dessine par dessus, et seul la zone de texte, qui utilise <b><a href="https://www.khronos.org/opengl/" target="_blank">OpenGL</a> + <a href="https://www.freetype.org/" target="_blank">FreeType</a> + <a href="https://github.com/harfbuzz/harfbuzz" target="_blank">Harfbuzz</a></b> est pour l'instant &quot;ajoutée&quot; aux images enregistrées. <br />
<br />
<br />
<b><font size="3">Les besoins</font></b><br />
<br />
On souhaite pouvoir créer et utiliser une instance d'un objet canvas : il faudra donc un onglet actif (sinon une fenêtre active si pas d'onglets). On supposera cette condition réalisée en tant que pré-requis.<br />
<br />
On suppose de plus qu'une instance du Canvas existe dans l'onglet actif, et que le curseur de la souris survole la zone &quot;dessinable&quot;, qui n'est autre que celle de l'image en cours de visualisation (par exemple une vidéo en cours de lecture)<br />
<br />
<b>À chaque tour de boucle principale, si l'onglet contenant l'instance est actif, on doit pouvoir :</b><br />
<br />
<ul><li style=""> <b><font color="#0000FF">créer un nouvel objet avec la souris</font></b>. Méthode: clic gauche+faire glisser sans relâcher: le curseur dessine l'objet dont l'icône est active ;</li><li style=""> <b><font color="#0000FF">afficher dynamiquement </font></b>l'objet en train d'être dessiné ;</li></ul><br />
<div style="margin-left:40px"><u><font color="#008000"><b>Conditions</b></font></u> : un objet pouvant être dessiné doit être sélectionné dans la barre d'outils (par un clic gauche)</div><div style="margin-left:40px"><u><b><font color="#008000">Action réalisée</font></b></u> : on ne dessinait pas avant le clic gauche. Une fois le bouton gauche enfoncé, sans relâcher, on fait glisser le curseur de la souris.</div><div style="margin-left:40px"><u><b><font color="#008000">Effet attendu</font></b></u>: l'objet est dessiné progressivement. Si on revient en arrière, la modification est visualisée en temps réel</div><br />
<ul><li style=""> <b><font color="#0000FF">ne pas mettre le processeur à genoux</font></b> pendant la manipulation (actuellement : limitation à 60 fps environ =&gt; ~ 12% d'un coeur).</li></ul><br />
<div style="margin-left:40px"><u><b><font color="#008000">Action réalisée</font></b></u> : en ralentissant la boucle principale, ne pas dépasser une certaine charge par coeur  // Optimisation</div><br />
<ul><li style=""> <b><font color="#0000FF">dessiner</font></b> de nouveaux objets ;</li><li style=""> <b>sélectionner</b> le <b><font color="#0000FF">type d'objet</font></b> à dessiner ;</li><li style=""> <b><font color="#0000FF">interagir</font></b> avec les objets dessinés ;</li><li style=""> <b><font color="#0000FF">effacer</font></b> des objets ;</li><li style=""> <b><font color="#0000FF">sélectionner</font></b> un objet (dans ce cas, sa couleur est modifiée);</li><li style=""> <b><font color="#0000FF">visualiser</font></b> quand un <b><font color="#0000FF">objet</font></b> est <b><font color="#0000FF">survolé</font></b> ;</li><li style=""> <b><font color="#0000FF">déplacer</font></b> les objets ;</li><li style=""> <b><font color="#0000FF">modifier l'ordre d'empilement</font></b> d'un objet : monter ou descendre d'un niveau,placer un objet à l'avant ou à l'arrière :</li><li style=""> <b><font color="#0000FF"> supprimer le dernier objet créé</font></b> ;</li><li style=""> <b><font color="#0000FF"> supprimer tous les objets</font></b> dessinés.</li></ul><br />
<br />
Exemple pour illustrer le <b><font color="#0000CD">déplacement vertical des objets dans la pile</font></b> des objets dessinés (cf ci-dessous) : l'objet jaune était sous l'objet rouge. Mais on ne veut pas toucher le bleu.<br />
<br />
<b>AVANT</b> :<br />
<br />
<div style="text-align: center;"> <img src="https://www.developpez.net/forums/attachments/p578435d1599123300/c-cpp/c/cgi-c/objet_jaune_avant.png/" border="0" alt="Nom : objet_jaune_avant.png
Affichages : 6637
Taille : 25,1 Ko"  style="float: CONFIG" /><br />
<br />
</div><br />
<b>APRÈS</b> :<br />
<br />
<div style="text-align: center;"><img src="https://www.developpez.net/forums/attachments/p578436d1599123347/c-cpp/c/cgi-c/objet_jaune_apres.png/" border="0" alt="Nom : objet_jaune_apres.png
Affichages : 6683
Taille : 31,0 Ko"  style="float: CONFIG" /><br />
<br />
</div><br />
<br />
Tous ces besoins ont permis de définir <b><font color="#0000FF"><a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/inc/canvas.hpp" target="_blank">l'interface du canvas</a><br />
</font></b><br />
<br />
<br />
<b>Commentaires sur l'interface</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:168px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td valign="top"><pre style="margin: 0">


namespace md

{
    class Canvas
    {
        public:
            Canvas();
            ~Canvas();</pre></td></tr></table></pre>
</div><b>Tous les booléens ci-dessous servent à déterminer ce qu'est en train de faire l'utilisateur, et si on peut dessiner, stocker les informations ou autre chose.<br />
</b><br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:168px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td valign="top"><pre style="margin: 0">
            bool           init();
            void           update(ImVec2);

            bool           addObject();
            bool           adding_circle;
            bool           adding_circle2;
            bool           adding_preview1;
            bool           adding_preview2;
            bool           adding_rect;
            bool           adding_rect2;</pre></td></tr></table></pre>
</div><b>bcol contient la couleur de l'objet dessiné (flat color pour l'instant)</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:144px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td valign="top"><pre style="margin: 0">

            ImVec4  bcol;
            // future use
            // ImVec4 ocol;

            int            iconWidth;
            int            iconHeight;
            int            frame_padding;</pre></td></tr></table></pre>
</div><b>setMouseValid() : confirme que le curseur de la souris est bien dans la zone image, lorsqu'on dessine le cadre qui sera contenu dans la loupe.<br />
<br />
preview() : contient l'indice de l'objet sélectionné, ainsi que la couleur qui sera retournée (sélectionné ou simplement survolé ?)<br />
</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:120px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td valign="top"><pre style="margin: 0">

            void           setMousePosValid(int, float);
            void           preview(int selectedObject, ImU32, int, float, float);
            void           updateSelectedArea(ImVector &lt;ImVec2&gt; points, ImU32, float);
            // FIXME, usefull
            //void           setSelectedAreaPoints(ImVec2, ImVec2);</pre></td></tr></table></pre>
</div><b>draw() : ajoute la pile d'objet dans la pile graphique</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">  
          int            draw();
            void           clean();</pre></td></tr></table></pre>
</div><b>remove() : permet de supprimer un objet en connaissant sa position dans la pile des objets dessinés.</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">

            bool           remove(unsigned int);</pre></td></tr></table></pre>
</div><b>moveObjectTo() permet de déplacer verticalement un objet dans la pile des objets dessinés : monter / descendre d'un niveau, placer à l'arrière ou à l'avant, ou encore supprimer.</b><br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:60px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br /></div></td><td valign="top"><pre style="margin: 0">
            bool           moveObjectTo(unsigned int, int);</pre></td></tr></table></pre>
</div><b>Menu contextuel  (n'existe que si un objet est sélectionné)</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">

            void           showObjectsStackPopupMenu(unsigned int);</pre></td></tr></table></pre>
</div><b>Les méthodes ci-dessous retournent <b>vrai</b> si on survole le type d'objet (donné par leur nom). Les algorithmes correspondants seront présentés dans une prochaine partie.<br />
</b><br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td valign="top"><pre style="margin: 0">

            bool           insideCircle(ImVec2, ImVec2, float);
            bool           intersectEmptyCircle(ImVec2, ImVec2, float, float);

            //             intersection when : (x == A) OR (x === B)  OR ((vec A)*(vec B) &lt; EPSILON  AND  ( x bettwen xB and xC) AND ( y  between yB and yC))
            bool           intersectSegment(ImVec2 /* mousePos */, ImVec2 /* Point_A */ , ImVec2  /* Point_B */);
            bool           mousePosIsPoint(ImVec2 /* mousePos */, ImVec2 /* aGivenPoint */);

            bool           insideSimpleArrow(ImVec2, ImVector&lt;ImVec2&gt;, ImVector&lt;ImVec2&gt;);
            bool           insidePolygon(ImVec2, ImVector&lt;ImVec2&gt;);

            //             only horizontal rectangle are drawn
            bool           insideFilledRectangle(ImVec2, ImVector&lt;ImVec2&gt;);
            bool           intersectEmptyRectangle(ImVec2, ImVector&lt;ImVec2&gt;, ImVector&lt;ImVec2&gt;);

            bool           insideEllipse(ImVec2, float, ImVec2, ImVec2); // includes empty ellipse
            bool           intersectEmptyEllipse(ImVec2, float, ImVec2, ImVec2, float /* thickness */);

            bool           insideCurve(ImVec2, ImVector&lt;ImVec2&gt;);
            bool           insideArrow(ImVec2, ImVector&lt;ImVec2&gt;);</pre></td></tr></table></pre>
</div><b>Les méthodes ci-dessous permettent de sélectionner un objet, de retrouver l'indice de celui qui est actuellement actif (s'il existe), de retourner la valeur du booléen permettant de savoir si un objet est actuellement dans l'état actif (sélectionné) </b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:132px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td valign="top"><pre style="margin: 0">

   
         inline void    setSelected(unsigned int selectedObject) { currentActiveDrawnObjectIndex = selectedObject;}
            inline unsigned int   getCurrentActiveDrawnObjectIndex(void) { return currentActiveDrawnObjectIndex ; }

            inline bool    getIsAnObjectSelected (void) { return anObjectIsCurrentlySelected; }
            inline void    setObjectCurrentlySelected (bool bValue) { anObjectIsCurrentlySelected = bValue; }</pre></td></tr></table></pre>
</div><b>La méthode ci-dessous retourne la couleur de l'objet (sélectionné ou simplement survolé ? )</b><br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">

            ImU32          getBackgroundColor(unsigned int);</pre></td></tr></table></pre>
</div><b>La méthode ci-dessous retrouve les paramètres des objets dans la pile des objets dessinés, en fonction du type d'objet.</b><br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:96px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br /></div></td><td valign="top"><pre style="margin: 0">


            void           catchPrimitivesPoints(void);
            int            show();</pre></td></tr></table></pre>
</div><b>Les fonctions -initialisation des textures OpenGL-  ci-dessous permettent de dessiner les icônes des objets dans la barre d'outils.</b><br />
<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:120px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td valign="top"><pre style="margin: 0">

            void           loadCanvasObjectsIcons(void);
            void           createCanvasObjectsImagesTexIds(void);
            void           cleanCanvasObjectsImagesTexIds(void);

            GLuint         canvasObjectImageTexId[CANVAS_OBJECTS_TYPES_MAX];</pre></td></tr></table></pre>
</div><b>chaque icône d'objet pouvant être dessiné est convertie en objet matriciel OpenCV de type cv::Mat()</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">

            cv::Mat        canvasObjectImage[CANVAS_OBJECTS_TYPES_MAX];</pre></td></tr></table></pre>
</div><b>Ci-dessous : différents pointeurs et variables pour la gestion du Canvas</b><br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:156px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td valign="top"><pre style="margin: 0">

            md::TextCanvas * mp_TextCanvas;

            ImVec2           topLeft;
            ImVec2           bottomRight;

            ImDrawList *     p_drawList;
            ImVec2           mouse_pos_in_image;
            ImVector &lt;ImVec2&gt; arrow_points;</pre></td></tr></table></pre>
</div><b>Ci-dessous zoom_area points et un vecteur de 2 points (ayant chacun 2 composantes),  qui définissent la position de la partie à zoomer avec la loupe</b><br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:84px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br /></div></td><td valign="top"><pre style="margin: 0">

            ImVector &lt;ImVec2&gt; zoom_area_points;
            DrawnObject      aDrawnObject;</pre></td></tr></table></pre>
</div><b>L'objet en cours d'élaboration est un objet de type DrawnObject, dont la définition est donnée dans canvas_objects.hpp</b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:156px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td valign="top"><pre style="margin: 0">

            std::vector &lt;DrawnObject&gt; currentlyDrawnObjects;

        private:
            unsigned int    currentActiveDrawnObjectIndex;
            bool            anObjectIsCurrentlySelected;
    };

} /* namespace md */</pre></td></tr></table></pre>
</div><br />
<b><font size="3"><b>Principes de fonctionnement</b></font></b><br />
<br />
Les méthodes essentielles utilisées dans la boucle principale sont canvas::preview(), canvas::draw() et canvas::update(). La méthode canvas::moveTo() est appelée dans le menu popup de canvas::update().<br />
<br />
Autour de la <b><font color="#0000FF">ligne 1444, dans Sources/src/Application/miniDart.cpp </font></b>:<br />
<br />
On retrouve l'adresse de la liste des objets à dessiner par Dear ImGui (fenêtres, widgets, etc), à laquelle on va ajouter notre pile d'objets, puis les coordonnées du curseur de la souris.<br />
<br />
À l'étape suivante, on appelle canvas::preview() avec les coordonnées du curseur de la souris dans la zone image, dans le cas où un type d'objet pouvant être dessiné serait défini, l'utilisateur réunissant les conditions pour que quelque chose soit dessiné.<br />
<br />
Puis on appelle canvas::draw() pour dessiner tout ce qui doit l'être, y compris l'éventuel nouvel objet ajouté dans la pile.<br />
<br />
Enfin, on appelle canvas::update qui passe en revue tous le vecteur des objets à dessiner, et détecte pour chacun d'entre eux s'il est survolé par le curseur de la souris. Si un objet est survolé, son paramètre hovered passe à vrai, et la couleur de cet objet changera. S'il est sélectionné, c'est une autre couleur qui sera affichée, afin de pouvoir faire la distinction entre survolé et sélectionné (on peut modifier certains de ces paramètres, le déplacer etc).<br />
<br />
Ainsi : <br />
- si l'objet n'est pas sélectionné, mais simplement survolé, sa couleur change ;<br />
- si plusieurs objets ont une zone commune, ce sont tous les objets survolés simultanément qui changent de couleur ;<br />
- si l'objet est sélectionné par un clic gauche sans relâchement, il pourra être déplacé ;<br />
- s'il est sélectionné, avec un clic droit on pourra le déplacer verticalement, changer sa couleur, ou même encore le supprimer.<br />
<br />
<b>Remarque</b> : les algorithmes utilisés permettant de savoir si le curseur de la souris est à l'intérieur de la forme de l'objet (ou pas) seront présentés dans une prochaine partie.<br />
<br />
<br />
<font size="3"><b>Dessiner ou pas</b></font><br />
<br />
Pour cela on capture la position du curseur de la souris sur l'écran, dans une fenêtre en utilisant la méthode <font color="#0000FF">ImGui::IsItemHovered()</font><br />
Si la zone image, à l'intérieur de la fenêtre racine est survolée : on peut dessiner<br />
Sinon : on ne peut pas dessiner.<br />
<br />
<br />
<font size="3"><b>Prévisualisation d'un objet à dessiner</b></font><br />
<br />
Concerne la création d'un nouvel objet, c'est à dire qu'avant le clic gauche sans relâchement, on n'était pas en train de dessiner. On doit donc capturer 2 positions -distinctes et suffisamment éloignées- du curseur à l'écran, détecter l'appui sur un bouton, si on se déplace sans relâcher, ou le relâchement simple d'un bouton, car il faut &quot;comprendre&quot; ce que fait l'utilisateur, et traduire ses actions. Tout ça à environ 60 images par seconde ! (parce que je limite, sinon, le rafraîchissement atteint entre 200 et 400 images par seconde sur un i7@1,8 GHz, mais le processeur est à 100% de sa charge dans ce cas.<br />
<br />
Lorsqu'on relâche le bouton de la souris :<br />
- si les dimensions de l'objet sont inférieures à quelque chose de détectable : on ne fait rien<br />
- si les dimensions sont supérieures à une certaine limite, on stocke le type, les paramètres essentiels de l'objet dans la pile<br />
<br />
Dans tous les cas on vide l'objet à prévisualiser.<br />
<br />
Pour des raisons d'<b>OPTIMISATION</b>, <u>certains paramètres essentiels</u> au dessin sont <b>calculés PENDANT la pré-visualisation</b>.<br />
<br />
Méthode :  canvas::preview()<br />
<br />
<br />
<font size="3"><b>Dessin d'un objet</b></font><br />
<br />
On dessine, dans l'ordre correspondant à la création, tous les objets stockés dans la pile de type <font color="#0000FF">ImGui:: DrawList()</font>. Si la pile est vide, on ne dessine rien. La couleur de l'objet sera calculée en temps réel, et dépendra de l'état de l'objet : survolé et/ou sélectionné<br />
<br />
<font size="3"><b>Stockage des données</b></font><br />
<br />
Pour chaque objet, des données sont stockées lorsque l'utilisateur &quot;relâche&quot; le bouton gauche de la souris, après avoir dessiné un objet.<br />
<br />
Pour stocker proprement les paramètres d'un objet, la structure DrawnObject a été créée, et son interface est définie dans le fichier d'en-tête <a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/inc/canvas_objects.hpp" target="_blank">canvas_objects.hpp<br />
</a><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">
typedef struct DrawnObject
{</pre></td></tr></table></pre>
</div>anObjectype est un entier qui contient le type d'objet, qui n'est pas forcément un objet à dessiner. Exemple : SELECT_CURSOR.<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:60px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br /></div></td><td valign="top"><pre style="margin: 0">
    unsigned int anObjectType;// object type, defines properties</pre></td></tr></table></pre>
</div>thickness: contient l'épaisseur du trait<br />
P1P4 : contient la distance entre 2 points, ou un rayon. Si la valeur est inférieure à une valeur seuil, l'objet dessiné avec preview n'est pas ajouté à la pile d'objets à dessiner.<br />
<br />
Les commentaires permettent de comprendre l'utilité de chacun des paramètres stockés avec chaque objet présent dans la pile des objets à dessiner..<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td valign="top"><pre style="margin: 0">
    float        thickness;
    float        P1P4;        // line length
    float        R2_in;       // (intern radius)^2
    float        R2_out;      // (extern radius)^2

    // ellipse properties must be calculated just after preview
    ImVec2       F1;          // ellipse focus point 1
    ImVec2       F2;          //         focus point 2
    float        long_axis;    // ellipse long axis
    float        radius_x;    // ellipse x radius
    float        radius_y;    // ellipse y radius
    float        rotation;    // rotation angle (CTRL key + MouseDrag)

    float        arrowLength;
    float        arrowWidth;

    bool         selected;
    bool         hovered;
    bool         record;
    bool         has_outline;

    ImVector &lt;ImVec2&gt;  arrowPolygon; // inside helpers
    ImVector &lt;ImVec2&gt;  Rect_ext; // inside helpers
    ImVector &lt;ImVec2&gt;  Rect_int; // inside helpers
    ImVector &lt;ImVec2&gt;  hullPoints; // inside helpers
    ImVector &lt;ImVec2&gt;  objectPoints;  // depends on the case
    ImU32  objBackgroundColor;</pre></td></tr></table></pre>
</div>TODO : mettre la bordure en surbrillance quand un objet est sélectionné, plutôt que modifier la couleur du fond<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:84px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br /></div></td><td valign="top"><pre style="margin: 0">

    ImU32  objOutlineColor;
} DrawnObject;</pre></td></tr></table></pre>
</div><b><br />
Merci d'avance pour tout retour constructif :-) Et si vous avez des questions, ou si vous trouvez une erreur ou une imprécision, n'hésitez surtout pas, à commenter ou à me contacter. <br />
<br />
Eric Bachard</b>  <br />
<br />
<b><font color="#0000FF"><br />
<a href="https://www.developpez.net/forums/blogs/1525847-ericb2/b9778/ecriture-canvas-cpp-dear-imgui-partie-1-8/" target="_blank">Précédent : dessiner sur l'écran (partie 1)</a> </font></b> <b><font color="#0000FF">      À SUIVRE (partie3 : la barre d'outils )</font></b></blockquote>

]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b9784/ecriture-d-canvas-cpp-dear-imgui-partie-2-8/</guid>
		</item>
		<item>
			<title><![CDATA[Écriture d'un canvas en C++, avec Dear ImGui    (PARTIE 1 sur 8)]]></title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b9778/ecriture-d-canvas-cpp-dear-imgui-partie-1-8/</link>
			<pubDate>Sun, 30 Aug 2020 15:06:53 GMT</pubDate>
			<description>*Introduction* 
 
Cette étude...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore"><b>Introduction</b><br />
<br />
Cette étude est divisée en 8 parties (1 billet de blog par partie) :<br />
<br />
  <b>1</b>. <b><font color="#008000">Dessiner sur l'écran</font></b> avec <a href="https://github.com/ocornut/imgui" target="_blank"><b><font color="#0000CD">Dear ImGui</font></b></a><br />
  <b>2</b>. <font color="#008000"><b>La classe canvas</b></font> (améliorations et tests)<br />
  <b>3</b>. <b><font color="#008000">La barre d'outils</font></b> des objets pouvant être dessinés<br />
  <b>4</b>. <b><font color="#008000">Sélectionner un objet</font></b> et le modifier<br />
  <b>5</b>. <font color="#008000"><b>Déplacement vertical</b></font> d'un objet dans le dessin : choix faits<br />
  <b>6</b>. Création d'un <b><font color="#008000">menu contextuel</font></b> avec <a href="https://github.com/ocornut/imgui" target="_blank"><b><font color="#008000">Dear ImGui</font></b></a><br />
  <b>7</b>. <b><font color="#008000">Déplacement horizontal d'un l'objet</font></b> dans la fenêtre<br />
  <b>8</b>. <b><font color="#008000">Utilisation du canvas</font></b> dans le logiciel miniDart<br />
<br />
Comme expliqué dans un précédent billet <a href="https://www.developpez.net/forums/blogs/1525847-ericb2/b9757/2-animations-dear-imgui-fade-in-fade-out-heartbeat-effect" target="_blank"><b>2 animations pour Dear ImGui</b></a>, j'utilise <a href="https://github.com/ocornut/imgui" target="_blank"><b><font color="#0000CD">Dear ImGui</font></b></a> avec bohneur depuis 4 ans,<br />
ce qui me permet d'assurer la <b><font color="#0000FF">portabilité sous Windows de mon logiciel, tout en écrivant le code sous Linux</font></b>.<br />
<br />
<b><font color="#B22222">Vous pouvez tester ce canvas avec le logiciel ci-dessous. Un binaire pour Windows est disponible en ligne, et vous le trouverez en suivant le lien donné ci-dessous. Liens:</font></b><br />
<br />
- <a href="https://framagit.org/ericb/miniDart" target="_blank"><b>Version de développement et code source du logiciel miniDart</b></a><br />
<br />
Et pour le code lié au sujet de l'article, c'est ici : <br />
- <a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/inc/canvas.hpp" target="_blank"><b>Interface de la classe canvas</b></a><br />
- <a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/src/Canvas/canvas.cpp" target="_blank"><b>Implémentation</b></a><br />
<br />
<a href="https://framagit.org/ericb/miniDart" target="_blank"><b><font color="#0000CD">miniDart</font></b></a> étant un logigiel d'analyse de la performance sportive (en développement), le besoin d'annoter les vidéos en cours d'analyse a rapidement été formulé par les quelques personnes qui ont l'amabilité de me faire des retours. En fait, les besoins ne sont pas très importants, et je travaille souvent seul.<br />
<br />
L'idée, c'est de pouvoir <u>annoter une vidéo, tout en continuant de la visionner</u> : on fait un arrêt sur image, <br />
et hop, on insère un commentaire, dont la durée et quelques paramètres (police, taille, couleur, fond coloré ou pas ...) sont paramétrables.<br />
<br />
Remarque: pour l'instant, on ne peut insérer qu'un seul commentaire, mais ça devrait être résolu prochainement.<br />
<br />
De plus, quelquefois, on peut avoir besoin d'<b><font color="#008000">insérer une flèche</font></b> (droite ou courbée aussi), ou simplement de dessiner à main levée. <u>D'où l'idée de créér un canvas</u>, activable via un bouton, pour ajouter cette fonctionnalité très utile.<br />
<br />
J'insiste: si vous avez une suggestion une idée à soumettre, n'hésitez pas à vous créer un compte et à faire une demande (voir<br />
ici :<a href="https://framagit.org/ericb/miniDart/-/issues" target="_blank"><font color="#0000CD"> <b>issues dédiées à miniDart</b></font></a><br />
<br />
<br />
<b>Pourquoi avoir tout écrit moi-même ?<br />
</b><br />
En fait, j'ai eu beau chercher, je n'ai PAS trouvé de site décrivant un canvas écrit en C++ (n'hésitez pas à faire suivre vos liens si vous en connaissez un). <br />
<br />
Ce qui se rapproche le plus, c'est <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" target="_blank"><font color="#0000FF">celui proposé par la fondation Mozilla</font></a>, très bien écrit, et qui fonctionne très bien. Mais c'est un autre langage (Java script ?).<br />
<br />
Mais ne soyons pas naïfs, je parie qu'il en existe mais les entreprises ne partagent malheureusement pas leur code ... tout en étant très contentes d'en trouver sur <a href="https://github.com/" target="_blank"><b>github</b></a>, ou <a href="https://framagit.org/public/projects" target="_blank">framagit</a> que j'utilise comme plein de monde.<br />
<br />
Alors, je l'ai fait moi-même, même si c'est loin d'être parfait, au moins tout est de moi. <b>Je vous remercie pour votre indulgence</b>, sachant que je ne suis pas un professionnel de la programmation, et que j'ai fait ça sur mon temps libre.<br />
<br />
Enfin, je rappelle que <b><font color="#0000FF">toute aide est la bienvenue ... :-)</font></b><br />
<br />
Comme le développement a demandé pas mal de temps, je vais présenter la progression dans les idées et l'implémentation, dans l'ordre réel, et diviser les articles en plusieurs parties :<br />
<br />
<b>Partie 1. dessiner sur l'écran</b><br />
<br />
Exemple fourni par Dear ImGui: il s'appelle &quot;Custom Rendering&quot;, cf la copie d'écran ci-dessous<br />
<br />
<br />
<div style="text-align: center;"><img src="https://www.developpez.net/forums/attachments/p578185d1598795198/bases-donnees/sybase/sybase-definition-symboles/custom_rendering.png/" border="0" alt="Nom : custom_rendering.png
Affichages : 9649
Taille : 39,9 Ko"  style="float: CONFIG" /></div><br />
<br />
La seconde image présente les primitives (formes de base).<br />
<br />
<div style="text-align: center;"><img src="https://www.developpez.net/forums/attachments/p578186d1598796472/bases-donnees/sybase/sybase-definition-symboles/canvas_primitives.png/" border="0" alt="Nom : canvas_primitives.png
Affichages : 5425
Taille : 48,8 Ko"  style="float: CONFIG" /></div>Une <b>nouveauté récente</b>, ce sont les <b>polygones &quot;ngon&quot;</b>, et les formes circulaires dont on peut faire varier le nombre de segments. Dès que la pile est vide, on remarquera que les boutons de suppression ont disparu.<br />
<br />
<a href="https://github.com/ocornut/imgui/releases" target="_blank"><b>voir la page releases de Dear ImGui</b></a>  pour les derniers changements. En résumé, on ne dessine pas grand chose, mais au moins la suggestion est faite !<br />
<br />
<br />
<br />
<b>Choix des objets à dessiner</b><br />
<br />
<br />
Dans les choix pour le <b>canvas</b> qui sera présenté, les <b>primitives</b> que nous utiliserons sont :<br />
<ul><li style=""> rectangle plein ;</li><li style=""> rectangle évidé ;</li><li style=""> cercle plein ;</li><li style=""> cercle évidé ;</li><li style=""> ellipses pleines (voir:  ) ;</li><li style=""> ellipses évidées + la possibilité d'effectuer une rotation en maintenant la touche CTRL enfoncée ;</li><li style=""> les traits simples ;</li><li style=""> le tracé à main levée sera obtenu avec une suite de cercles de petits rayons, collés les uns à la suite des autres ;</li><li style=""> le tracé de flèches simples ;</li><li style=""> le tracé de flèches &quot;arrondies&quot;. Ces flèches sont obtenues à l'aide d'une courbe de Bezier 4 points (le premier et le dernier, les deux autres étant calculés et pris au 1/3 et le suivant aux 2/3 de la distance</li></ul><br />
<br />
La liste des objets pouvant être dessinés (+ d'autres dont on aura besoin) sont donnés dans le fichier d'en-tête<br />
[**canvas_objects.hpp**](<a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/inc/canvas_objects.hpp" target="_blank">https://framagit.org/ericb/miniDart/...as_objects.hpp</a>)<br />
<br />
Noter aussi la liste des chemins des images définies comme des constantes (pour des raisons de sécurité évidentes).<br />
<br />
Deux thèmes sont prévus, mais seul le thème DARK sera utilisé pour l'instant.<br />
<br />
<br />
<br />
<b>Réutilisation avec le dessin des flèches</b><br />
<br />
<br />
L'algorithme du tracé de la flèche est donné dans la documentation. En voici l'essentiel<br />
<br />
<div style="text-align: center;"><img src="https://www.developpez.net/forums/attachments/p578191d1598798020/bases-donnees/sybase/sybase-definition-symboles/principe_calcul.png/" border="0" alt="Nom : principe_calcul.png
Affichages : 5793
Taille : 43,5 Ko"  style="float: CONFIG" /></div><br />
Le principe est très simple : l'utilisateur définit 2 points, et les coordonnées des autres sont calculées cf l'équation ci-dessous pour le point C. <br />
<br />
<div style="text-align: center;"><img src="https://www.developpez.net/forums/attachments/p578189d1598797891/bases-donnees/sybase/sybase-definition-symboles/coordonnees_point_c.png/" border="0" alt="Nom : coordonnees_point_C.png
Affichages : 6057
Taille : 34,8 Ko"  style="float: CONFIG" /></div><br />
Pour le reste, le calcul des coordonnées des autres points, et l'algorithme du tracé complet sont donnés dans le document mentionné ci-dessus.<br />
<br />
<img src="https://www.developpez.net/forums/attachments/p578195d1598799929/bases-donnees/sybase/sybase-definition-symboles/implementation2.png/" border="0" alt="Nom : implementation2.png
Affichages : 5139
Taille : 307,8 Ko"  style="float: CONFIG" /><br />
<br />
Rappel : il s'agit de mode immédiat, et tout se passe dans une boucle infinie. À chaque tour, c'est l'état de variables statiques qui définit<br />
ce qui doit être fait et/ou dessiné.<br />
<br />
Remarquer l'exemple du gradient (il pourrait devenir utile), et les deux piles possibles permettant de dessiner en avant plan et en<br />
arrière plan, indépendamment de ce qui est déjà dessiné. Comprendre : tout au dessus, ou tout en dessous. <br />
<br />
Utilisation : on peut simplement tracer des traits, et les empiler. On peut aussi les dépiler en les supprimant séquentiellement (le dernier,<br />
puis celui d'avant ... etc, jusqu'au premier trait tracé).  D'un point de vue logiciel, on crée donc une pile (ou un vecteur en C++) de traits d'une couleur donnée : push / pop pour dépiler<br />
<br />
<br />
Lien : <a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/documentation/french/miniDart_creation_de_fleches.pdf" target="_blank"><b><font color="#0000FF">Algorithme utilisé pour dessiner une flèche avec Dear ImGui  (document .pdf)</font></b></a><br />
<br />
<br />
Tests réalisés<br />
<br />
En fait, dessiner quelque chose n'est pas le plus gros problème. En étudiant l'API (détaillée dans ImGui.h), on comprend vite ce qu'il faut pour dessiner quelque chose.<br />
<br />
Le vrai problème est ailleurs : quid des clics de souris ?<br />
<br />
<b>Méthode &quot;preview&quot;</b><br />
<br />
Pour résoudre le problème, on convient de considérer : les clics droits et/ou gauche de la souris, si le bouton vient d'être appuyé, s'il vient d'être relâché, ou si la souris est déplacée SANS que le bouton ait été relâché.<br />
<br />
Le choix fait :  clic sans relâcher ET en déplaçant la souris : on est en train de créer un déplacement. Le point origine P1 est donc stocké en mémoire, et dès qu'on relâche la souris, la position finale du curseur servira de point numéro 2.<br />
Les 2 points P1 et P2 permettant ainsi sans ambiguïté de dessiner un trait, un rectangle, un cercle, etc, selon la figure sélectionnée.<br />
<br />
<br />
Dans le code, ça donne :<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:72px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br /></div></td><td valign="top"><pre style="margin: 0">
void md::Canvas::preview(int selectedObject, ImU32 color, int w, float ratio, float outline_thickness)
{</pre></td></tr></table></pre>
</div>Signature de la méthode : on a besoin de la couleur de l'objet à dessiner, du ratio (lié au rapport largeur sur hauteur de l'écran, outline_thickness définit la finesse du tracé<br />
<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:156px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td valign="top"><pre style="margin: 0">
   setMousePosValid(w, ratio);

    aDrawnObject.radius_x = 1.0f + ImGui::GetMouseDragDelta().x;
    aDrawnObject.radius_y = 1.0f + ImGui::GetMouseDragDelta().y;

    if (fabs(aDrawnObject.radius_x) &lt;= 1.0f)
        aDrawnObject.radius_x = 1.0f;

    aDrawnObject.rotation = ImGui::GetIO().KeyCtrl ? aDrawnObject.radius_y / aDrawnObject.radius_x : 0.0f;</pre></td></tr></table></pre>
</div>L'astuce ci-dessus permet, via un appui sur la touche CTRL de faire tourner une ellipse, dans le cas où l'on en dessinerait une.<br />
<br />
N.B. : le code de l'ellipse est accessible <a href="https://framagit.org/ericb/miniDart/-/blob/master/PATCHES/imgui_changes_in_miniDart_2020_03_17.diff" target="_blank"><b><font color="#0000FF">dans ce patch </font></b></a><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td valign="top"><pre style="margin: 0">

    switch(aDrawnObject.anObjectType)
    {
        case SELECTED_OBJECT:
        case EMPTY_RECTANGLE:
        case EMPTY_CIRCLE:
        case EMPTY_ELLIPSE:
        case FILLED_RECTANGLE:
        case FILLED_CIRCLE:
        case FILLED_ELLIPSE:
        case SIMPLE_LINE:
        case SIMPLE_ARROW:
        {
            catchPrimitivesPoints();
        }
        break;</pre></td></tr></table></pre>
</div>Pour les objets définis ci-dessus, une méthode appelée catchPrimitives est appelée. Elle permettra, via certains algorithmes (vus dans une prochaine partie), de savoir si un objet est survolé par le curseur de la souris.<br />
<br />
L'objet en train d'être &quot;prévisualisé&quot; est appelé  aDrawnObject.<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td valign="top"><pre style="margin: 0">

        case RANDOM_LINE:
            static bool adding_circle   = false;

            if (adding_circle)
            {
                aDrawnObject.anObjectType = selectedObject;
                aDrawnObject.objectPoints.push_back(mouse_pos_in_image);

                for (int i = 0 ; i &lt; aDrawnObject.objectPoints.size(); i++)
                {
                    ImGui::GetOverlayDrawList()-&gt;AddCircleFilled(ImVec2(mp_TextCanvas-&gt;image_pos.x + aDrawnObject.objectPoints[i].x,
                                                                        mp_TextCanvas-&gt;image_pos.y + aDrawnObject.objectPoints[i].y),
                                                                 aDrawnObject.thickness,
                                                                 aDrawnObject.objBackgroundColor,
                                                                 8);
                }

                if (!ImGui::GetIO().MouseDown[0])
                {</pre></td></tr></table></pre>
</div>                   On vient de relâcher le bouton gauche de la souris (souris relâchée !)<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:96px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br /></div></td><td valign="top"><pre style="margin: 0">
                  adding_circle = false;

                    if (getIsAnObjectSelected() == false)
                        currentlyDrawnObjects.push_back(aDrawnObject);</pre></td></tr></table></pre>
</div>                   ci-dessus : on a capturé les caractéristiques de l'objet qui sera ajouté à la pile des objets à dessiner.<br />
                   On prépare le tour suivant : il faut nettoyer l'objet utilisé pour la prochaine saisie.<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:192px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td valign="top"><pre style="margin: 0">
                    while (!aDrawnObject.objectPoints.empty())
                    {
                        aDrawnObject.objectPoints.pop_back();
                    }
                }
            }

            if (ImGui::IsItemHovered())
            {

                if ( (ImGui::IsMouseClicked(0)||ImGui::IsMouseClicked(1)) &amp;&amp; !ImGui::IsMouseDragging(0) )
                {</pre></td></tr></table></pre>
</div>                  L'utilisateur n'a pas relâché le bouton de la souris, mais il s'est arrêté : on arrête d'ajouter des points.<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:156px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td valign="top"><pre style="margin: 0"> 

                   adding_circle = false;
                }

                if ( (ImGui::IsMouseClicked(0)||ImGui::IsMouseClicked(1)) &amp;&amp; ImGui::IsMouseDragging(0) )
                    adding_circle = true;

                if ( (!adding_circle &amp;&amp; ImGui::IsMouseClicked(0)) )
                {</pre></td></tr></table></pre>
</div>                   ci-dessus, l'utilisateur a cliqué ET il n'était PAS en train de dessiner : on part de ce point<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td valign="top"><pre style="margin: 0"> 


                   if (getIsAnObjectSelected() == false)
                        aDrawnObject.objectPoints.push_back(mouse_pos_in_image);

                    adding_circle = true;
                }
            }
        break;

        case RANDOM_ARROW:
            static bool adding_circle2   = false;

            if (adding_circle2)
            {
                aDrawnObject.anObjectType = selectedObject;
                arrow_points.push_back(mouse_pos_in_image);

                for (int i = 0 ; i &lt; arrow_points.size(); i++)
                {
                    ImGui::GetOverlayDrawList()-&gt;AddCircleFilled( ImVec2(mp_TextCanvas-&gt;image_pos.x + arrow_points[i].x, mp_TextCanvas-&gt;image_pos.y + arrow_points[i].y), aDrawnObject.thickness, aDrawnObject.objBackgroundColor, 8);
                }

                if (!ImGui::GetIO().MouseDown[0])
                {</pre></td></tr></table></pre>
</div>                    Souris relâchée ! Le second point est maintenant défini, et on va calculer les points (pendant la prévisualisation pour optimiser, et on va ajouter l'objet avec toutes ses caractéristiques dans le vecteur des objets à dessiner. Le fait de pré-calculer certaines caractéristiques permet de tout dessiner très vite (sinon, on aurait à refaire tous ces calculs à chaque tour de boucle !!<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br /></div></td><td valign="top"><pre style="margin: 0">

                    adding_circle2 = false;

                    aDrawnObject.objectPoints.push_back(arrow_points[0]);
                    aDrawnObject.objectPoints.push_back(arrow_points  [(int)(arrow_points.size()/3.0f)]);
                    aDrawnObject.objectPoints.push_back(arrow_points[(int)((2*arrow_points.size())/3.0f)]);
                    aDrawnObject.objectPoints.push_back(arrow_points[arrow_points.size()-1]);
                    aDrawnObject.P1P4 = sqrtf(  (aDrawnObject.objectPoints[1].x - aDrawnObject.objectPoints[0].x)
                                               *(aDrawnObject.objectPoints[1].x - aDrawnObject.objectPoints[0].x)
                                              + (aDrawnObject.objectPoints[1].y - aDrawnObject.objectPoints[0].y)
                                               *(aDrawnObject.objectPoints[1].y - aDrawnObject.objectPoints[0].y));

                    if (getIsAnObjectSelected() == false)
                        currentlyDrawnObjects.push_back(aDrawnObject);

                    arrow_points.clear();
                    aDrawnObject.objectPoints.clear();
                }
            }

            if (ImGui::IsItemHovered())
            {
                if ( (ImGui::IsMouseClicked(0)||ImGui::IsMouseClicked(1)) &amp;&amp; !ImGui::IsMouseDragging(0) )
                    adding_circle2 = false;

                if ( (ImGui::IsMouseClicked(0)||ImGui::IsMouseClicked(1)) &amp;&amp; ImGui::IsMouseDragging(0) )
                    adding_circle2 = true;

                if ( (!adding_circle2 &amp;&amp; ImGui::IsMouseClicked(0)) )
                {
                    if (getIsAnObjectSelected() == false)
                        arrow_points.push_back(mouse_pos_in_image);

                    adding_circle2 = true;
                }
            }
        break;

            //case TEXT_OBJECT:
        case SELECT_CURSOR:
        case NOT_A_DRAWN_OBJECT:
        {
            if (adding_rect)
            {
                adding_preview1 = true;
                zoom_area_points.push_back(mouse_pos_in_image); // catch the second point

                if (!ImGui::GetIO().MouseDown[0])
                   adding_rect = adding_preview1 = false;
            }


            if (ImGui::IsItemHovered())
            {

                if ( (((ImGui::IsMouseClicked(0)||ImGui::IsMouseClicked(1) )  &amp;&amp; (!zoom_area_points.empty()))) &amp;&amp; !ImGui::IsMouseDragging(0) )
                {
                    adding_rect = false;
                    adding_preview1 = false;
                    zoom_area_points.pop_back();
                    zoom_area_points.pop_back();
                }

                if ( (!adding_rect &amp;&amp; ImGui::IsMouseClicked(0)) )
                {
                    zoom_area_points.push_back(mouse_pos_in_image);
                    adding_rect = true;
                }
            }

            updateSelectedArea(zoom_area_points, color, outline_thickness);
            reorder_points(&amp;topLeft, &amp;bottomRight);

            if (adding_preview1)
                zoom_area_points.pop_back();
        }
        break;

        case TEXT_OBJECT:
        default:
        break;
    }
}</pre></td></tr></table></pre>
</div><br />
Pour le code complet , voir la méthode <a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/src/Canvas/canvas.cpp" target="_blank"><b><font color="#0000CD">canvas::preview</font></b></a><br />
<br />
<br />
<br />
<b><font color="#0000FF">  <a href="https://www.developpez.net/forums/blogs/1525847-ericb2/b9784/ecriture-canvas-cpp-dear-imgui-partie-2-8/" target="_blank">Suivant : partie2 : la classe canvas</a> </font></b></blockquote>


<!-- attachments -->
	<div class="blogattachments">
		
		
			<fieldset class="blogcontent">
				<legend>Images attachées</legend>
				
			</fieldset>
		
		
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b9778/ecriture-d-canvas-cpp-dear-imgui-partie-1-8/</guid>
		</item>
		<item>
			<title><![CDATA[2 animations pour Dear ImGui : "Fade In / Fade Out" et  "heartBeat effect"]]></title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b9757/2-animations-dear-imgui-fade-in-fade-out-heartbeat-effect/</link>
			<pubDate>Wed, 05 Aug 2020 23:13:01 GMT</pubDate>
			<description>*Introduction* 
Depuis...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore"><font size="2"><font color="#0000CD"><b>Introduction</b></font></font><br />
Depuis plusieurs années, j'utilise <b><font color="#0000FF"><a href="https://github.com/ocornut/imgui" target="_blank">Dear ImGui</a></font></b> pour l'interface utilisateur dans mon logiciel <font color="#0000FF"><b><a href="https://framagit.org/ericb/miniDart" target="_blank">miniDart</a></b></font>. N.B. : gros changements à venir (non publics pour l'instant).<br />
<br />
Après avoir cherché 6 mois (j'ai testé environ 30 GUI avant de choisir <b><font color="#0000FF"><a href="https://github.com/ocornut/imgui" target="_blank">Dear ImGui</a></font></b>), cette API était finalement la seule à pouvoir fonctionner sous Linux et Windows quasiment de la même façon. La portabilité est directe par cross compilation et ça fonctionne extrêmement bien sous les 2 OS. Au passage un petit mot sur TrollTech, qui se fout de la gueule des petits développeurs avec sa licence Qt à un prix délirant, pour celui qui veut s'affranchir de lier statiquement à 100Mo de blobs pour sortir un binaire, avec des dépendances délirantes et -probablement- inutiles.<br />
<br />
Cette API qui n'a besoin que de <font color="#0000FF"><b><a href="https://www.opengl.org/" target="_blank">OpenGL**</a></b></font> permet de faire une version de démonstration très rapidement, déjà présentée récemment dans<b> <a href="https://open-source.developpez.com/actu/288769/Ubisoft-sponsorise-la-bibliotheque-d-interface-utilisateur-pour-Cplusplus-Dear-ImGui-suite-a-son-adhesion-au-Blender-Development-Fund-pour-soutenir-l-animation-open-source/" target="_blank">cet article</a></b>, est franchement géniale pourvu que l'on prenne le temps de lire la très bonne documentation qui se trouve .... dans le code. <br />
<br />
Oui, tout se mérite :) <br />
<br />
**(toutefois, une version <font color="#0000FF"><b><a href="https://en.wikipedia.org/wiki/DirectX" target="_blank">DirectX</a></b></font> ou <font color="#0000FF"><b><a href="https://www.khronos.org/vulkan/" target="_blank">Vulkan</a> </b></font>doit pouvoir être écrite en 10 min AMHA 8-) )<br />
<br />
Dans cet article, je présente rapidement deux animations que j'ai créées récemment, et qui sont utilisables avec <b>cette API géniale</b> :<br />
<br />
<ul><li style="">  La première s'appelle &quot;<b>fade in / fade out</b>&quot;. Elle a été inspirée par <b>Sonoro123</b>, développeur et contributeur régulier à <b><font color="#0000FF"><a href="https://github.com/ocornut/imgui" target="_blank">Dear ImGui</a></font></b>. (voir :<font color="#0000FF"><b> <a href="https://github.com/ocornut/imgui/issues/1925" target="_blank">cette issue</a></b></font> pour l'historique)<br /></li><li style="">  La seconde, &quot;<b>heartbeat effect</b>&quot;, est une idée que j'ai eue, juste pour vérifier qu'on pouvait refaire l'effet wow qui existait sous Mac OS X il y a quelques années :-)</li></ul><br />
<br />
<font size="2"><font color="#0000CD"><b>Télécharger le code</b></font></font><br />
Les deux fichiers contenant le code font partie de <font color="#0000FF"><b><a href="https://framagit.org/ericb/miniDart" target="_blank">miniDart</a></b></font>, mais on peut les associer à tout autre chose, et leur code est sous <b>Licence MIT</b>.<br />
<br />
Les deux fichiers contenant les deux fonctionnalités sont placés ici :<br />
<ul><li style=""><a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/src/3rdparty/imgui_custom/imgui_fade_in_out.cpp" target="_blank"><font color="#000080"><b>Implémentation</b></font></a> <br /></li><li style=""><a href="https://framagit.org/ericb/miniDart/-/blob/master/Sources/src/3rdparty/imgui_custom/imgui_fade_in_out.hpp" target="_blank"><font color="#000080"><b>Fichier d'en tête</b></font></a></li></ul><br />
<br />
Remarque : le namespace md utilisé avec la classe n'est pas essentiel pour vous, et peut aisément être supprimé.<br />
<br />
<font size="2"><font color="#0000CD"><b>Essayer et jouer avec</b></font></font><br />
Pour tester, j'ai mis un exemple dans le code source de <font color="#0000FF"><b><a href="https://framagit.org/ericb/miniDart" target="_blank">miniDart</a></b></font> (pour Linux, mais ça doit fonctionner facilement sous Windows aussi, car le code est totalement neutre (sauf erreur et oubli de ma part).<br />
<br />
Normalement, sous Linux, il n'y a rien d'autre à faire que télécharger le code source de <b><font color="#0000FF"><a href="https://github.com/ocornut/imgui" target="_blank">Dear ImGui</a></font></b><br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:36px;">git clone <a href="https://github.com/ocornut/imgui.git" target="_blank">https://github.com/ocornut/imgui.git</a></pre>
</div>Ensuite, télécharger les fichiers <br />
<ul><li style=""> <b>Makefile</b></li><li style=""> <b>imgui_fade_in_out.cpp</b></li><li style=""> <b>imgui_fade_in_out.hpp</b></li><li style=""> <b>main.cpp</b></li></ul><br />
<br />
Vous trouverez tout <font color="#0000FF"><b><a href="https://framagit.org/ericb/miniDart/-/tree/master/Sources/src/3rdparty/imgui/examples/example_sdl_opengl3" target="_blank">à cette URL</a></b></font><br />
<br />
Placer tous ces fichiers dans imgui/examples/example_sdl_opengl3 en écrasant ceux qui font partie de <b><font color="#0000FF"><a href="https://github.com/ocornut/imgui" target="_blank">Dear ImGui</a></font></b>. <br />
<br />
Et taper &quot;make&quot;<br />
<br />
=&gt; lancer le binaire et ça doit fonctionner comme prévu :D<br />
<br />
<br />
<font color="#FF0000"><b>Important :</b></font><br />
Pour revenir en arrière et retrouver le code de base du répertoire exemple avec SDL2 + OpenGL3, il suffit de taper : <b> make clean &amp;&amp; git diff . | patch -R  </b>   (ne pas oublier le point !)<br />
<br />
<b>Comme le gif que j'ai essayé d'attacher ne fonctionne pas, l'animation est visible</b> <a href="https://user-images.githubusercontent.com/23149049/78675289-1f86e700-78e5-11ea-98df-d8c9af1ae72a.gif" target="_blank"><font size="2"><font color="#FF0000"><b>ICI </b></font></font></a> (très incomplet car depuis, la fenêtre disparaît complètement)<br />
<br />
<br />
<font color="#0000FF"><b><font size="3">Merci d'avance pour tout retour et / ou suggestion d'amélioration !!</font></b></font></blockquote>


<!-- attachments -->
	<div class="blogattachments">
		
		
			<fieldset class="blogcontent">
				<legend>Images attachées</legend>
				
			</fieldset>
		
		
		

	</div>
<!-- / attachments -->
]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b9757/2-animations-dear-imgui-fade-in-fade-out-heartbeat-effect/</guid>
		</item>
		<item>
			<title><![CDATA[Implémentation naïve d'une table de hachage en C]]></title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b9730/implementation-naive-d-table-hachage-c/</link>
			<pubDate>Fri, 24 Jul 2020 17:36:48 GMT</pubDate>
			<description>*Introduction* 
 
Cet article...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore"><b>Introduction</b><br />
<br />
Cet article présente brièvement une implémentation &quot;naïve&quot; d'une table de hachage en C, à base de liste chaînée. L'idée, c'est simplement de valider le modèle et de jouer avec, car le code n'a rien de professionnel. Il pourrait (devrait) facilement être porté en C++. <br />
<br />
J'ajoute qu'il doit même exister des bibliothèques comme Boost qui proposent des exemples prêts à l'emploi, et certainement plus robustes. En fait, je n'en sais rien, mais je ne serais pas surpris. <br />
<br />
<font color="#0000FF">Donc c'est en C, c'est tout :-)</font><br />
<br />
Comme le but c'est de tester, tout est disponible en ligne. Si vous souhaitez faire des essais, <font color="#FF0000"><b>notez que ça ne fonctionne que sous Linux</b></font>, mais ça doit se porter facilement sous Mac OS X (je ne sais pas si popen existe, et strlcpy est protégé par des macros, car Apple propose sa propre implémentation).<br />
<br />
<b><div style="text-align: center;"><a href="https://framagit.org/ericb/some_little_usefull_C_applications/-/tree/master/table_de_hachage" target="_blank"> =&gt; lien pour télécharger le code source</a></div></b><div style="text-align: center;"><br />
<br />
</div><b>Commentaires sur le code :</b><br />
<br />
<ul><li style="">j'ai beaucoup (trop) documenté le code. Je vais bientôt les enlever (git diff version1...version2 &gt; documentation.diff permettra de les retrouver facilement)</li><li style=""> les saisies, que ce soit d'une chaîne de caractères, d'un entier court (signé), ou encore d'un nombre réel (y compris en notation scientifique) sont effectuées par l'API saisie, que j'ai écrite pour éviter à mes élèves de perdre du temps avec les entrées/sorties en C, qui sont une véritable horreur (cette API m'a demandé beaucoup de temps, et j'ai probablement encore quelques trous dans la raquette). Cette abstraction étant réalisée c'est beaucoup plus simple pour eux.</li><li style=""> la compilation est réalisée par make (+ un Makefile, qui peut aussi être utilisé avec LateX)        [étude d'un Makefile]</li><li style=""> les sources sont découpées en plusieurs fichiers .c  [notion de compilation séparée, cf  <font color="#0000CD">Méthodologie de programmation en C, de JP Braquelaire</font>]</li><li style=""> les flags de compilation permettent de traquer un maximum de warnings possibles, afin d'être sûr que le code est suffisamment propre. Il suffit de commenter une ligne dans le Makefile pour simplifier</li></ul><br />
<br />
<b> Les dépendances sont les suivantes :</b><br />
<br />
<ul><li style=""> git si vous souhaitez utiliser le dépôt complet</li><li style=""> gcc ( sudo apt-get install build-essential)</li><li style=""> make pour la création du binaire</li><li style=""> gdb (pour déboguer le binaire qui inclut les symboles ad hoc)</li></ul><br />
<br />
À venir (un jour) : amélioration de la documentation, avec des compléments sur la complexité et les propriétés des tables de hachages<br />
<br />
Si vous avez des questions, n'hésitez pas. En particulier, j'ai commencé à écrire une documentation type approche documentaire autour de ce sujet, mais toute aide est bienvenue !!<br />
<br />
<br />
<i><font color="#0000FF">Merci d'avance pour vos retours, et vos suggestions d'améliorations, et n'hésitez pas à me contacter si vous avez des questions. </font></i><br />
<br />
<font size="2"><b>Quelques définitions</b></font><br />
<br />
En informatique, une <font color="#0000FF">table de hachage</font> est une <font color="#0000FF">structure de données</font> qui permet l'association de <font color="#0000FF">paires clé/valeur</font>. Il s'agit d'un <font color="#0000FF">tableau</font> ne comportant pas d'ordre (un tableau est indexé par des entiers).<br />
<br />
La clé étant une chaîne de caractère, la valeur un nombre, ou une suite de nombres comme un numéro de téléphone ou n'importe quelle donnée associée à une &quot;valeur&quot;. Il est aussi possible, certaines fois, d'avoir plusieurs valeurs pour la même <font color="#0000FF">clé</font>, par exemple dans le  but d'éviter des <font color="#0000FF">collisions</font>.<br />
<br />
<b><br />
Principe de fonctionnement</b> : on accède à chaque élément de la table via sa <font color="#0000FF">clé</font>. Les <font color="#0000FF">paires</font> sont stockées dans les <font color="#0000FF">alvéoles</font> du tableau. En fonction de la méthode utilisée, le <font color="#0000FF">remplissage</font> peut poser problème ou pas. Selon la nature de la table de hachage, le nombre d'alvéoles peut être fixe ou variable dynamiquement (comme ici).<br />
<br />
<br />
<b>Les opérations que l'on peut réaliser avec cette table de hachage sont :</b><br />
<br />
<ul><li style=""> <i>créer la table (et l'initialiser) ;</i></li><li style=""> <i>ajouter une paire clé/valeur ;</i></li><li style=""> <i>supprimer une paire en donnant la clé (la valeur sera supprimée en même temps que la clé) ;</i></li><li style=""> <i>chercher si une clé existe dans la table ;</i></li><li style=""> <i>retrouver la valeur associée à une clé ;</i></li><li style=""> <i>modifier la valeur associée à une clé.</i></li></ul><br />
<br />
Dans notre cas, la taille de la table est a priori indéfinie (mais de valeur finie), et dépend des ressources mémoire dont on dispose.<br />
<br />
Il n'y a <font color="#0000FF">pas de relation d'ordre</font> dans une table de hachage, et la position des paires clé-valeur est pseudo-aléatoire dans cette table.<br />
<br />
<b>Illustration</b> : imaginons que l'on crée la clé &quot;AAA&quot;,associée à la valeur &quot;1984&quot;. Ensuite, on ajoute deux clés &quot;Odyssée de l'espace&quot; (associée à &quot;2001&quot;)  et enfin la clé &quot;Marignan&quot; associée à &quot;1515&quot;. On peut évidemment supprimer la clé AAA (la valeur sera perdue avec la suppression de cette clé) et recréer AAA. Mais cette fois, l'alvéole qui contient AAA sera en fin de liste, et aura changé de place. <font color="#0000FF">L'ordre n'est donc pas prévisible, ni immuable.</font><br />
 <br />
<br />
Cette structure n'est donc pas adaptée au feuilletage (browsing) de données voisines. Des types de structures de données comme les arbres équilibrés [4], généralement plus lents (en O(log n) [3]) et un peu plus complexes à implémenter, maintiennent une structure ordonnée. <br />
<br />
On associe la notion de <font color="#0000FF">dictionnaire</font> (très utilisé avec Mac OSX) à la notion de table de hachage.<br />
<br />
<b>Exemple de table de hachage</b><br />
<br />
Pour illustrer la notion de table de hachage, on utilise l'exemple donné sur <font color="#0000FF">wikipedia</font> [1], cf figure ci-dessous.<br />
<img src="https://www.developpez.net/forums/attachments/p575791d1595611402/autres-langages/general-visual-basic-6-vbscript/vb-6-anterieur/vb6-graphisme-tracer-cercle-pset/hash01.png/" border="0" alt="Nom : hash01.png
Affichages : 14831
Taille : 67,1 Ko"  style="float: CONFIG" /><br />
<br />
Les données saisies par l'utilisateur sont en bleu et en vert. L'indice associé à l'index est attribué de façon interne par le logiciel, et représente la position dans la liste chaînée qui n'est pas ordonnée. Dans le code l'indice sera appelé <font color="#8B4513">refcount</font> (très utile en C++ aussi) dans le code écrit en langage C.<br />
<br />
<br />
<u>Remarque</u> : ne pas confondre <font color="#0000FF">table de hachage</font> avec <font color="#0000FF">fonction de hachage</font> : On nomme fonction de hachage, de l'anglais<b> hash function </b>(hash*: pagaille, désordre, recouper et mélanger) par analogie avec la cuisine, une fonction particulière qui, à partir d'une donnée fournie en entrée, calcule une empreinte numérique servant à identifier rapidement la donnée initiale, au même titre qu'une signature pour identifier une personne. Les fonctions de hachage sont utilisées en informatique et en cryptographie notamment pour reconnaître rapidement des fichiers ou des mots de passe. <br />
<br />
Les deux notions sont toutefois proches, puisqu'on réalise une opération au sens mathématique sur la clé, pour obtenir la valeur. Quand la valeur est obtenue (grâce à une fonction qui prend pour argument la clé), on parle de fonction de hachage. <br />
<br />
<b>Exemple</b> : calcul d'une somme de contrôle md5 d'une chaîne de caractère (qui peut être longue)<br />
<br />
<br />
<font color="#0000FF"><font size="2"><b>Pour en savoir plus</b></font></font><br />
<br />
<b>Sources type URL :</b><br />
<br />
[1] <a href="https://fr.wikipedia.org/wiki/Table_de_hachage" target="_blank">https://fr.wikipedia.org/wiki/Table_de_hachage</a><br />
[2] <a href="https://fr.wikipedia.org/wiki/Fonction_de_hachage" target="_blank">https://fr.wikipedia.org/wiki/Fonction_de_hachage</a><br />
<br />
[3] <a href="https://fr.wikipedia.org/wiki/Comparaison_asymptotique" target="_blank">https://fr.wikipedia.org/wiki/Comparaison_asymptotique</a><br />
[4] <a href="https://fr.wikipedia.org/wiki/Arbre_équilibré" target="_blank">https://fr.wikipedia.org/wiki/Arbre_équilibré</a><br />
<br />
La page du département informatique de l'<font color="#0000FF">ENS Cachan</font> (bouh, Paris Saclay maintenant) :<br />
<a href="http://www.dptinfo.ens-cachan.fr/Agregation/" target="_blank">http://www.dptinfo.ens-cachan.fr/Agregation/</a><br />
<br />
Document de <font color="#0000FF">Mme Cristina Sirangelo</font> :<br />
<a href="http://www.dptinfo.ens-cachan.fr/Agregation/Algo13-14/3-tables-hachage.pdf" target="_blank">http://www.dptinfo.ens-cachan.fr/Agr...es-hachage.pdf</a><br />
<br />
<a href="http://www.lsv.fr/~jacomme/agreg/index.html" target="_blank">http://www.lsv.fr/~jacomme/agreg/index.html</a> : <font color="#0000FF">fiches d'algorithmique</font><br />
<br />
Les dictionnaires (Université de Montréal) : <br />
<a href="https://www.iro.umontreal.ca/~hamelsyl/Dictionnaires4.pdf" target="_blank">https://www.iro.umontreal.ca/~hamels...ionnaires4.pdf</a></blockquote>

]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b9730/implementation-naive-d-table-hachage-c/</guid>
		</item>
		<item>
			<title>Produire ses vidéos (audio + vidéo synchronisés) sous Linux, pour le prix de la webcam</title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b9478/produire-videos-audio-p-video-synchronises-sous-linux-prix-webcam/</link>
			<pubDate>Wed, 03 Jun 2020 16:23:18 GMT</pubDate>
			<description>Pour ceux que cela intéresse,...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore">Pour ceux que cela intéresse, j'ai repris un projet (on dit &quot;forké&quot;) et j'ai ajouté ce dont j'avais besoin pour créer <b>ffmpeg-cpp2 sous Linux</b>.<br />
<br />
Il s'agit d'une <b>petite API en C++</b> qui encapsule les bibliothèques qui constituent ffmpeg (libavformat, libavutil, libavdevice, libavcodec, ...)<br />
<br />
L'utilisation basique de la webcam est donnée dans la petite démo qui s'appelle remux_webcam (voir ci-dessous). Mais les filtres, dont je ne parle pas ici, c'est encore plus génial !<br />
<br />
<br />
<b>L'API est basée sur la notion de flux entrée/sortie</b> :<br />
<ul><li style="">source audio : raw (par exemple venant de la webcam), ou frame (bande son venant d'une vidéo donnée ;</li><li style="">source vidéo (un fichier, un flux réseau, un flux raw (venant d'une webcam)</li><li style="">l'extraction du son ou de l'image ;</li><li style="">le filtrage  (plus de 100 filtres, issus de ffmpeg : rotation, zoom, crop etc) ;</li><li style="">le démultiplexage : on extrait le son ou l'image d'un flux (le décodage est automatique) ;</li><li style="">on peut ensuite mélanger les flux que l'on a extrait avec un multiplexeur.</li></ul><br />
<br />
En gros, on peut faire ce qu'on veut, quelle que soit la source, et SANS être obligé d'utiliser l'interface graphique du développeur. Comme ça, vous faîtes ce que vous voulez.<br />
<br />
Exemple : j'ai associé la bande son de Hells Bells (AC-DC) au début de la vidéo BigBuckBunny. ça rend pas mal du tout :-)<br />
<br />
<b>Le dépôt (framagit) est là :<a href="https://framagit.org/ericb/ffmpeg-cpp2" target="_blank"> ffmpeg-cpp2 sur framagit</a><br />
</b><br />
Afin de protéger mon travail, j'ai mis la licence GPL V3, mais je pense repasser un jour sous LGPL.<br />
<br />
Dans les démos, on a plein d'exemples qui devraient fonctionner tout droit.<br />
<br />
Voir : <b><a href="https://framagit.org/ericb/ffmpeg-cpp2/-/tree/master/demos" target="_blank">démos</a><br />
</b><br />
Application à la webcam : <br />
<br />
<ul><li style=""> <b>j'utilise alsa  + v4l2  sous Linux</b>  (sous Windows, ça pourrait être dshow à la place de v4l2, et DirectSound à la place d'alsa)</li><li style=""> le démultiplexeur pour la webcam (partie vidéo) est le même que pour les sources type fichier, mais j'ai surchargé le constructeur, pour des raisons d'utilisabilité</li><li style=""> pour le son, j'ai implémenté une nouvelle classe, dérivant d'une source classique </li></ul><br />
<br />
<b>Les problèmes rencontrés</b> : la synchronisation, et la bande son qui ne durait quasiment pas.  Le problème venait du fait qu'il fallait deux fils d'exécution séparés pour le son et la vidéo sur la même webcam. Sinon alsa (avec pulse ou hw:1,0 etc) fonctionne super bien (j'utilise Linuxmint)<br />
<br />
<b>Les dépendances </b>: <br />
<br />
<ul><li style=""><b>ffmpeg</b> (toutes les bibliothèques associées en fait. J'utilise la version 4.2.2</li><li style="">la <b>libpthread</b> (pour l'enregistrement séparé son / image synchrone)</li><li style="">certaines bibliothèques (mais on peut s'en passer) de <b>codecs</b> (h264, liblamemp3, libvpx-vp9, etc</li><li style=""><b>v4l2</b> , qui est l'API standard pour Linux</li><li style="">la <b>libasound</b> (bibliothèque alsasound)</li><li style="">la bibliothèque c++ standard : <b>std::chrono</b> (pour l'instant, on enregistre une durée donnée, mais quand il y aura un bouton start/stop, la durée ne sera plus un problème)</li><li style=""><b>std::fstream</b> pour la suppression des fichiers audio et vidéo intermédiaires</li></ul><br />
<br />
<b><font size="2">TODO : implémenter VAAPI pour le décodage et l'encodage</font></b><br />
<br />
<br />
Le contenu du programme est trivial, mais pour une vraie application, j'aurais créé des nouvelles classes (TODO). <b><i> Les commentaires sont dans le code</i></b>.<br />
<br />
<br />
Initialisation :<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td valign="top"><pre style="margin: 0">/*
 * File remux_webcam.cpp
 * Copyright Eric Bachard / 2020 05 08
 * This document is under GPL v3 license
 * see : <a href="http://www.gnu.org/licenses/gpl-3.0.html" target="_blank">http://www.gnu.org/licenses/gpl-3.0.html</a>
 */

#include &lt;iostream&gt;
#include &lt;chrono&gt;
#include &lt;ffmpegcpp.h&gt;
#include &lt;thread&gt;         // std::thread
#include &lt;fstream&gt;        // std::remove

static bool bRecording = false;

using namespace ffmpegcpp;
using std::string;
using std::cerr;

//#ifdef ALSA_BUFFER_SIZE_MAX
#undef ALSA_BUFFER_SIZE_MAX
#define ALSA_BUFFER_SIZE_MAX  524288

// les fichiers temporaires contenant le son et les images
const char * audio_file = &quot;../videos/audio.mp4&quot;;  // aac (s32le ?)
const char * video_file = &quot;../videos/video_H264.mp4&quot;;  // h264</pre></td></tr></table></pre>
</div><br />
<b>Enregistrement Audio :</b><br />
<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br /></div></td><td valign="top"><pre style="margin: 0">void record_Audio()
{
    const char * audioDevice = &quot;pulse&quot;;  // fonctionne avec pulseaudio ici
    //const char * audioDevice = &quot;hw:1,0&quot;;
    const char * audioDeviceFormat = &quot;alsa&quot;;

    // on crée une instance du container audio
 
   Muxer* Amuxer  = new Muxer(audio_file);   

    // paramètres usuels
    int audioSampleRate = 44100;
    int audioChannels   = 2;


    // on choisit d'encoder le son avec le codec aac, avec une instance de l'encodeur qui suit 
    AudioCodec         *   audioCodec = new AudioCodec(AV_CODEC_ID_AAC);
    AudioEncoder       *   audioEncoder = new AudioEncoder(audioCodec, Amuxer);


    // définition de la source audio (voir le constructeur pour retrouver le mécanisme
    // habituel de ffmpeg
    RawAudioFileSource *   audioFile = new RawAudioFileSource( audioDevice,
                                                            audioDeviceFormat,
                                                            audioSampleRate,
                                                            audioChannels,
                                                            audioEncoder);

    // préparation
    audioFile-&gt;PreparePipeline();

    // bRecording est une variable globale, car on doit pouvoir terminer le fil d'exécution
    while (!audioFile-&gt;IsDone())
    {
        audioFile-&gt;Step();

        if (bRecording == false)
            audioFile-&gt;Stop();
    }

    Amuxer-&gt;Close();

    if (audioEncoder != nullptr)
        delete audioEncoder;

    delete Amuxer;
}</pre></td></tr></table></pre>
</div><br />
<b>Même chose pour la vidéo : </b><br />
 <br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br /></div></td><td valign="top"><pre style="margin: 0">void record_Video()
{
    int width  = 1280; // 1920;
    int height = 720;  // 1080;
    int fps = 24;  // Logitech prefered fps value

    AVRational frameRate = { 24, 1 };

    // These are example video and audio sources used below.
    const char * videoDevice = &quot;/dev/video0&quot;;
    AVPixelFormat outputPixFormat= AV_PIX_FMT_NV12;

    Muxer* Vmuxer = new Muxer(video_file);
    H264Codec  * vcodec = new H264Codec();

    VideoEncoder * videoEncoder = new VideoEncoder(vcodec, Vmuxer, frameRate, outputPixFormat);

    Demuxer * demuxer  = new Demuxer(videoDevice, width, height, fps);
    demuxer-&gt;DecodeBestVideoStream(videoEncoder);
    demuxer-&gt;PreparePipeline();

    while (!demuxer-&gt;IsDone())
    {
        demuxer-&gt;Step();

        if (bRecording == false)
        {
            demuxer-&gt;Stop();
        }
    }

    // close the first muxers and save separately audio and video files to disk
    Vmuxer-&gt;Close();

    if (videoEncoder != nullptr)
        delete videoEncoder;

    delete Vmuxer;
}</pre></td></tr></table></pre>
</div><br />
<br />
<b>Création et assemblage de la vidéo finale : </b><br />
<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br /></div></td><td valign="top"><pre style="margin: 0">void create_final_Video()
{
    const char * final_file = &quot;../videos/final_video.mp4&quot;;  // h264 + aac (or vp9 + aac)

    Muxer* AVmuxer = new Muxer(final_file);

    AudioCodec * faudioCodec = new AudioCodec(AV_CODEC_ID_AAC);
    H264Codec  * fvcodec = new H264Codec();

    try
    {
        // Create encoders for both
        VideoEncoder* fvideoEncoder = new VideoEncoder(fvcodec, AVmuxer);
        AudioEncoder* faudioEncoder = new AudioEncoder(faudioCodec, AVmuxer);

        // Load both audio and video from a container
        Demuxer* videoContainer = new Demuxer(video_file);
        Demuxer* audioContainer = new Demuxer(audio_file);

        // Tie the best stream from each container to the output
        videoContainer-&gt;DecodeBestVideoStream(fvideoEncoder);
        audioContainer-&gt;DecodeBestAudioStream(faudioEncoder);

        // Prepare the pipeline. We want to call this before the rest of the loop
        // to ensure that the muxer will be fully ready to receive data from
        // multiple sources.
        videoContainer-&gt;PreparePipeline();
        audioContainer-&gt;PreparePipeline();

        // Pump the audio and video fully through.
        // To avoid big buffers, we interleave these calls so that the container
        // can be written to disk efficiently.
        while ( (!videoContainer-&gt;IsDone()) || (!audioContainer-&gt;IsDone()))
        {
            if (!videoContainer-&gt;IsDone())
                videoContainer-&gt;Step();

            if (!audioContainer-&gt;IsDone())
                audioContainer-&gt;Step();
        }

        // Save everything to disk by closing the muxer.
        AVmuxer-&gt;Close();
    }
    catch (FFmpegException e)
    {
        cerr &lt;&lt; e.what() &lt;&lt; &quot;\n&quot;;
        throw e;
    }

    delete AVmuxer;
}</pre></td></tr></table></pre>
</div><br />
<br />
<b>Et enfin, le programme principal </b>:<br />
<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br /></div></td><td valign="top"><pre style="margin: 0">int main(void)
{
    // obligatoire sinon la webcam n'est pas intialisée correctement
    avdevice_register_all();
    //avformat_network_init(); // future use

   // globale, permet de terminer proprement les 2 fils audio et vidéo
    bRecording = true;

    // on démarre l'enregistrement, en appelant séparément les deux 
   // process qui seront de fait quasi-synchronisés 
    std::thread first (record_Audio);
    std::thread second (record_Video);

    // on va enregistrer 1 min = 60 secondes
    auto start = std::chrono::steady_clock::now();
    auto current_time = std::chrono::steady_clock::now();
         std::chrono::duration&lt;double&gt; elapsed_seconds = current_time - start;
    do
    {
        current_time = std::chrono::steady_clock::now();
        elapsed_seconds = current_time - start;

    } while ((elapsed_seconds.count()) &lt; (60));


    // on annonce aux fils d'exécution qu'il faut terminer
    bRecording = false;

    // on recolle les morceaux, ce qui donne le temps de finaliser les
   // 2 fichiers temporaires, et de ne pas utiliser des fichiers en cours d'écriture

    first.join();
    second.join();


    // assemblage des 2 fichiers temporaires (audio / vidéo)
    create_final_Video();


    // c'est fini !!
    std::cout &lt;&lt; &quot;Encoding complete!&quot; &lt;&lt; &quot;\n&quot;;


   // il peut être intéressant de conserver les fichiers temporaires
#define TEST
#ifdef TEST
    std::remove(audio_file);
    std::remove(video_file);

     bool failed = (std::ifstream(audio_file) || std::ifstream(video_file));

    if(failed)
    {
        std::perror(&quot;Error opening deleted file&quot;);
        return 1;
    }
#endif

    return 0;
}</pre></td></tr></table></pre>
</div><br />
<b>Toute retour d'expérience et/ou aide est bienvenu, évidemment !!</b></blockquote>

]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b9478/produire-videos-audio-p-video-synchronises-sous-linux-prix-webcam/</guid>
		</item>
		<item>
			<title>Utiliser une webcam Logitech BRIO sous Linux</title>
			<link>https://www.developpez.net/forums/blogs/1525847-ericb2/b6750/utiliser-webcam-logitech-brio-sous-linux/</link>
			<pubDate>Wed, 26 Dec 2018 12:14:31 GMT</pubDate>
			<description>Tags : LogitechBRIO, Linux,...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore">Tags : LogitechBRIO, Linux, noyau, C++,  uvc-1.5, OpenCV, v4l2, video4linux2, USB3, webcam, <br />
<br />
<b>BUT : comment utiliser une webcam Logitech BRIO sous Linux, et où en est-on exactement ?</b><br />
<br />
<b>Avertissement</b> : il s'agit d'un article plutôt technique, mais sans prétention qui aborde des points touchant le développement Linux (C, code, noyau Linux).<br />
<br />
<b>Résumé</b> : ce n'est que le début. On commence par une description technique des conditions à remplir pour faire fonctionner le matériel, suivi d'une brève comparaison des caractéristiques (ce qu'apporte l'USB 3.0 et après). Je présente ce que j'ai fait pour que cela fonctionne. Enfin, des liens sont donnés pour ceux qui veulent tester, ou aller plus loin avec les webcams utilisant le protocole uvc 1.5, et permettre à ceux qui utilisent Linux d'avancer.<br />
<br />
Avant toute chose, je tiens à exprimer mes remerciements à <b>Laurent Pinchart </b>(<a href="http://www.ideasonboard.org/uvc/" target="_blank">http://www.ideasonboard.org/uvc/</a> et auteur du pilote du noyau uvcvideo), pour tout le travail qu'il a réalisé sur le sujet, depuis des années.<br />
<br />
<ul><li style=""><b>Prérequis : avoir du matériel adapté</b></li></ul><br />
L'utilisation d'une webcam est devenue quelque chose de très banal. Cependant, quand on veut l'utiliser sous Linux, on se demande quelquefois comment en tirer le meilleur parti. Je n'ai absolument rien à voir avec cette marque, et Logitech n'est pas vraiment connu pour aider le monde du libre, mais il faut reconnaître que cette marque propose des modèles remarquables, dont les références les plus connues sont les C615, C920, C922 et BRIO.<br />
<br />
Afin d'exploiter pleinement les possibilités de la webcam Logitech BRIO sous Linux, il faut que votre matériel possède un contrôleur de types USB3, et soit fonctionnel.<br />
Ce bus USB 3.x étant presque devenu la norme, si votre machine a moins d'un an, c'est normalement le cas (voir la notice de votre machine pour confirmer).<br />
<br />
Les trois premiers modèles exploitent le bus USB 2.0, et cela fonctionne déjà parfaitement. La dernière a des caractéristiques plus élaborées,et demande d'avoir un périphérique USB 3.0 pour fonctionner au maximum de ses possibilités.<br />
<br />
<b>IMPORTANT</b>&nbsp;: ce n'est pas la peine d'insister si vous n'avez pas de contrôleur compatible USB 3.0 (ou supérieur) sur votre machine, vous ne pourrez utiliser la BRIO qu'en mode compatibilité avec le bus 2.0.<br />
<br />
<ul><li style=""><b>Ordres de grandeur </b></li></ul><br />
** <b>La vitesse de transfert</b><br />
Les valeurs ci-dessous ont été obtenues avec dmesg + le périphérique correctement pris en charge)&nbsp;:<br />
<br />
<ul><li style="">USB 1.x : Device can operate at Full Speed (12&nbsp;Mbps)</li><li style="">USB 2.0 : Device can operate at High Speed (480&nbsp;Mbps)</li><li style="">USB 3.x : Device can operate at SuperSpeed (5&nbsp;Gbps)</li></ul><br />
<br />
<b>La vitesse de transfert</b> (donc la capacité à transporter des informations) est <u>multipliée par 10 entre l'USB 2.0 et l'USB 3.0</u>&nbsp;! C'est LA raison pour laquelle on peut obtenir un flux mjpeg en 4K avec l'USB 3.x. Cela n'est simplement pas possible avec de USB 2.x<br />
<br />
Lien avec log complet : <a href="https://github.com/ebachard/my_libuvc/blob/master/cameras/logitech_brio_4K_stream_edition.txt" target="_blank">https://github.com/ebachard/my_libuv...am_edition.txt</a><br />
<br />
Comparaison avec périphérique compatible USB 2.0 seulement (lien)&nbsp;:<br />
C922 : <a href="https://github.com/ebachard/my_libuvc/blob/master/cameras/logitech_C922_Pro_Stream_Webcam.txt" target="_blank">https://github.com/ebachard/my_libuv...eam_Webcam.txt</a><br />
C920 : <a href="https://github.com/ebachard/my_libuvc/blob/master/cameras/logitech_hd_pro_920.txt" target="_blank">https://github.com/ebachard/my_libuv...hd_pro_920.txt</a><br />
<br />
Autres cas&nbsp;: voir dans le répertoire contenant ces fichiers. N'hésitez pas à soumettre vos données ;-)<br />
<br />
** <b>les résolutions possibles</b><br />
<br />
En reprenant les logs mentionnés plus haut, on voit que la BRIO permet de streamer un flux mjpeg en 4k  (4096 x 2180 pixels), à 30 images par seconde.<br />
<br />
Voir cette discussion pour plus d'informations&nbsp;:  <a href="https://github.com/ebachard/my_libuvc/issues/1" target="_blank">https://github.com/ebachard/my_libuvc/issues/1</a><br />
<br />
<ul><li style=""><b>Le noyau Linux</b></li></ul><br />
C'est le programme qui fait le lien entre le matériel et l'utilisateur. Pour que cela fonctionne, il faudra un noyau 4.15 (sinon le compiler, voir la documentation plus bas). Pour que la prise en charge de la BRIO soit complète, il faut que le protocole 1.5 de la norme UVC soit pris en charge. Or, jusqu'à très récemment, la plus récente norme prise en charge sous Linux est la norme UVC 1.1. Ceci pour rappeler au passage que si on ne fait rien, et qu'on attend, il ne se passera rien. <b>Merci encore une fois à ceux qui font les choses.</b><br />
<br />
De plus, et parce que les correctifs sont très récents, vous devrez utiliser un noyau Linux qui prend en compte le protocole UVC 1.5. Vous devrez aussi installer une bibliothèque et des outils vidéo4linux2 (v4l2). Cet article donne quelques repères et propose quelques liens utiles pour celles et ceux qui voudraient expérimenter. <br />
<br />
Perspectives&nbsp;: une amélioration importante vient d'être intégrée à un noyau récent (4.17), et le grand public devra patienter un peu pour que tout devienne automatique.<br />
<br />
Le noyau maintenant&nbsp;: le correctif le plus important a été intégré dans le noyau 4.17 (il a été ajouté au noyau 3.16 depuis)<br />
<br />
Liens complémentaires&nbsp;:<br />
<a href="https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.17.4" target="_blank">https://cdn.kernel.org/pub/linux/ker...angeLog-4.17.4</a><br />
<a href="https://bugzilla.redhat.com/show_bug.cgi?id=1592454" target="_blank">https://bugzilla.redhat.com/show_bug.cgi?id=1592454</a><br />
<a href="https://cdn.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.16.61" target="_blank">https://cdn.kernel.org/pub/linux/ker...ngeLog-3.16.61</a><br />
<br />
<ul><li style=""><b>L'histoire</b> </li></ul><br />
N'arrivant pas à faire fonctionner ma BRIO, et après avoir cherché un peu, je suis tombé sur le site dédié au pilote uvcvideo (<a href="http://www.ideasonboard.org/uvc/" target="_blank">http://www.ideasonboard.org/uvc/</a>).<br />
Et par rebonds, j'ai finalement trouvé le diff qui expliquait tout (attention, c'est du code, timides s'abstenir  ;-) ) :<br />
<a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f620d1d7afc7db57ab59f35000752840c91f67e7" target="_blank">https://git.kernel.org/pub/scm/linux...752840c91f67e7</a><br />
<br />
Après avoir compris ce qu'il fallait modifier (et surtout où exactement !), j'ai tenté l'expérience, et j'ai tout noté dans un document (en anglais), que vous trouverez ici : <b><a href="https://github.com/ebachard/my_libuvc/tree/master/documentation/uvc1.5" target="_blank">https://github.com/ebachard/my_libuv...ntation/uvc1.5</a></b><br />
<br />
Je n'ai pas mis l'archive du noyau 4.15 en ligne, mais si vous ne savez pas comment compiler un noyau, ce sera plus simple d'installer un .deb (me demander en privé)<br />
<br />
N.B. : j'ai aussi mis les sources de ce document, écrit avec OOoLight, au format .odt. Ainsi, si vous avez des suggestions d'amélioration, vous pourrez facilement les soumetre (via github + un PR).<br />
<br />
<ul><li style=""><b>Video4linux2</b></li></ul><br />
Maintenant que cela fonctionne, comment utiliser votre webcam sous Linux ? <br />
<br />
Parmi les meilleurs logiciels, je vous conseille d'installer (vous avez le choix) : guvcview, qv4l2 ou et v4l2ucp. Vous pouvez aussi tester avec cheese, mais je l'utilise peu.<br />
<br />
Enfin, et là, c'est très sérieux : OBS (Open Broadcast Streamer) prend parfaitement en charge la BRIO. C'est votre bande passante (montante) qui devrait limiter vos ambitions, toutefois (il est préférable d'oublier de streamer du 4k pour l'instant).<br />
<br />
<ul><li style=""><b>Pan Tilt Zoom (PTZ)</b></li></ul><br />
La fonction PTZ réelle désigne une caméra avec des moteurs permettant des rotations dans deux directions : horizontale (pan = panoramique) et verticale (tilt). Cette fonction n'existe pas avec une webcam de type BRIO, mais en agrandissant la scène (zoom hardware), on peut cerner une zone, et faire un suivi identique à ce qu'on pourrait faire avec le PTZ &quot;réel&quot;.<br />
<br />
Pour revenir à ce qu'on peut faire avec une webcam, la BRIO possède un zoom (hardware) pouvant aller jusqu'à x5.0 (contre x2.0 pour les C920 et C922). Dans la pratique, on peut suivre un objet, ou une personne qui se déplace sur une scène (à condition de zoomer).<br />
<br />
La bibliothèque qui permet de faire cela s'appelle OpenCV (j'utilise la version 3.4.0). Cela fonctionne sous Windows (7 et +), mais évidemment, cela ne fonctionnait pas sous Linux et il a fallu mettre les mains dans le cambouis... Après quelques temps passés à tester, j'ai trouvé ce qui n'allait pas, et j'ai proposé un patch (incomplet, je l'ai amélioré depuis) à OpenCV. Cependant, je ne suis pas certain qu'il sera pertinent dans l'avenir. En effet, une réécriture de cette partie du code est en cours (mais ce sera dans la 4.x). C'est vous qui voyez.<br />
<br />
Lien&nbsp;: <a href="https://github.com/opencv/opencv/issues/12498" target="_blank">https://github.com/opencv/opencv/issues/12498</a><br />
<br />
En attendant que je puisse fournir une version Linux, et pour ceux qui veulent tester sous Windows, normalement, ça doit fonctionner avec miniDart (<a href="https://framagit.org/ericb/miniDart" target="_blank">https://framagit.org/ericb/miniDart</a>)<br />
Sous Linux, guvcview fonctionne super bien avec cette webcam (pourvu que le noyau la reconnaisse)<br />
<br />
<ul><li style=""><b>Liens pour aller plus loin </b></li></ul><br />
** Le protocole UVC 1.5<br />
<br />
** Microsoft extensions to USB video :  <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5" target="_blank">https://docs.microsoft.com/en-us/win...extensions-1-5</a><br />
Liens direct pour télécharger la norme : <a href="http://www.usb.org/developers/docs/devclass_docs/USB_Video_Class_1_5.zip" target="_blank">http://www.usb.org/developers/docs/d..._Class_1_5.zip</a><br />
<br />
** Webcam améliorée&nbsp;:<br />
L'incontournable kurokesu.com&nbsp;! Si vous souhaitez une version &quot;customisée&quot; d'une C920, C922 ou même d'une BRIO, il est indispensable d'aller sur ce site remarquable&nbsp;: <a href="https://www.kurokesu.com/main/blog/" target="_blank">https://www.kurokesu.com/main/blog/</a><br />
En particulier, pour les caméras USB&nbsp;: <a href="https://www.kurokesu.com/main/2016/01/16/manual-usb-camera-settings-in-linux/" target="_blank">https://www.kurokesu.com/main/2016/0...ings-in-linux/</a><br />
<br />
<ul><li style=""><b>Logiciels</b></li></ul><br />
** Télécharger miniDart (version Windows seulement)<br />
<br />
Il s'agit d'une version de développement, mais on peut faire des agrandissements du zoom, ce qui fait penser à une utilisation en microscope (peu puissant, mais le principe y est)&nbsp;: <br />
<a href="https://framagit.org/ericb/miniDart/blob/master/testing_version/miniDart_0.9.0_test.exe" target="_blank">https://framagit.org/ericb/miniDart/...0.9.0_test.exe</a> (cliquer sur Download, sinon il ne se passera rien ;-) )<br />
<br />
** OBS<br />
Le logiciel de braoadcast, qui fonctionne très bien sous Linux aussi&nbsp;:  <a href="https://obsproject.com/" target="_blank">https://obsproject.com/</a><br />
<br />
** V4L2<br />
Point d'entrée sur wikipedia <a href="https://fr.wikipedia.org/wiki/Video4Linux" target="_blank">https://fr.wikipedia.org/wiki/Video4Linux</a></blockquote>

]]></content:encoded>
			<dc:creator>ericb2</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/1525847-ericb2/b6750/utiliser-webcam-logitech-brio-sous-linux/</guid>
		</item>
	</channel>
</rss>
