From pouchintv-dev at baysse.fr Wed Jan 7 16:13:13 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Wed, 7 Jan 2009 16:13:13 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] lolo_32 | r162 - trunk Message-ID: <20090107151313.818DE5F330@mail.baysse.fr> Author: lolo_32 Date: 2009-01-07 16:13:13 +0100 (mer, 07 jan 2009) New Revision: 162 Modified: trunk/main.cpp Log: main.cpp: * corrige un boggue permettant plusieurs enregistrements de la même chaîne Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2008-12-29 21:51:51 UTC (rev 161) +++ trunk/main.cpp 2009-01-07 15:13:13 UTC (rev 162) @@ -1533,11 +1533,19 @@ break; case IDM_RECORD_CHANNEL_TS: + // On regarde si la chaîne n'est pas déjà en cours d'enregistrement + if (getGrabberChaine(ixChaineCourante) != -1) + // Chaîne déjà en cours d'enregistrement + break; if (start_record_ts(ixChaineCourante)>=0) update_record_menus(hMainWnd); break; case IDM_RECORD_CHANNEL_PS: + // On regarde si la chaîne n'est pas déjà en cours d'enregistrement + if (getGrabberChaine(ixChaineCourante) != -1) + // Chaîne déjà en cours d'enregistrement + break; if (start_record_ps(ixChaineCourante, ixSonCourant)>=0) update_record_menus(hMainWnd); break; From pouchintv-dev at baysse.fr Thu Jan 8 22:49:01 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Thu, 8 Jan 2009 22:49:01 +0100 Subject: [Pouchintv-dev] =?iso-8859-1?q?Pistes_audio_et_vid=E9o_dans_=22ch?= =?iso-8859-1?q?aines=2Exml=22?= References: <494ED004.5070101@baysse.fr> Message-ID: <926EFB2DC6B84B7DA3154B5C43E2F4B5@GILLES> > J'en profite : > Pourquoi sauvegarder dans le fichier "chaines.xml", les informations > telles que l'identifiant de la piste vidéo (Video_mpeg4 ou Video), les > pistes "son" ou les pistes "autres". > Quel en est l'intérêt, sachant que ceux-ci varient durant la diffusion : > certains programmes ont 1 piste sonore, puis le programme suivant en > aura 2, ou encore les chaînes payantes qui ont des diffusions en clair, > et donc, des diffusions différentes. > De plus, si on n'enregistre pas ces informations, PTVM les retrouve lors > de la première utilisation de la chaîne. Retour sur ce sujet : Je pense que la suppression de ces pistes pose beaucoup plus de problèmes que tu sembles le supposer. Outre celui dont je t'ai parlé tout-à-l'heure, à propos de l'affichage du correct du mode "Mp" (2 ou 4) dans le dialogue de configuration des chaînes, il y a aussi le cas des enregistrements programmés : Lorsque PouchinTV Mod commence l'enregistrement d'une émission qui a été programmée à l'avance, il se sert des informations mémorisées lors de la recherche de chaînes pour choisir la piste vidéo ainsi que la piste audio appropriées. Si l'enregistrement porte sur une chaîne qui n'a pas été regardée depuis que l'application a été lancée, le programme aura besoin de recharger ces informations avant de débuter l'enregistrement. Ce rechargement va demander un certain temps, les tables PAT et PMT dans le flux TS n'étant diffusées qu'à intervalles de temps réguliers (plusieurs fois par seconde, en principe, mais c'est encore trop long par rapport à la manière dont le programme est réalisé actuellement). Le résultat, dans l'état actuel des choses, est qu'en l'absence de sauvegarde de ces informations, PTVM démarre les enregistrements avec des données absentes ou même incorrectes, ce qui fait que les enregistrements programmés échouent s'ils portent sur une chaîne qui n'a pas été regardée depuis le lancement du programme. J'ai eu ce cas plusieurs fois, pour avoir juste tenté d'exécuter brièvement la r161 compilée. Une sauvegarde du fichier "chaines.xml" était réalisée à un moment donné de cette exécution, et cette sauvegarde, ensuite récupérée par mon PTVM "régulier" installé, lui faisait rater les enregistrements que j'avais demandés auparavant. J'ai tout lieu de croire qu'il en ira de même si le fichier "chaines.xml" généré par la r161 est récupéré par la même r161. Si on veut vraiment ne plus mémoriser les pistes audio et vidéo, alors il faut aussi modifier le programme pour s'assurer que ces pistes seront bien récupérées avant chaque début d'enregistrement. Ainsi, ça devrait marcher. Seulement, ça peut être délicat à bien mettre au point, et on a peut-être plus urgent à développer. Et même comme cela, des utilisateurs qui chercheraient à maintenir concurremment (pour une raison quelconque) une version de PTVM incluant cette sauvegarde et une version qui ne l'inclut pas pourraient avoir de sérieux problèmes. Je pense qu'il vaudrait mieux différer pour le moment la suppression de l'enregistrement des pistes audio et vidéo, et plutôt faire en sorte que cette sauvegarde devienne plus "propre", afin d'éviter les autres problèmes de corruption de la tables des chaînes déjà signalés par les utilisateurs de versions antérieures à la r161. Ce qui n'empêche pas de modifier progressivement le reste du programme pour s'assurer qu'une suppression future ne posera plus de problèmes. Gingko From pouchintv-dev at baysse.fr Sat Jan 10 17:58:22 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sat, 10 Jan 2009 17:58:22 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r163 - trunk Message-ID: <20090110165822.7B5275F424@mail.baysse.fr> Author: gingko Date: 2009-01-10 17:58:21 +0100 (sam, 10 jan 2009) New Revision: 163 Modified: trunk/LCD.cpp trunk/LCD.h trunk/Pouchin TV.sln trunk/Pouchin TV.vcproj trunk/base.cpp trunk/base.h trunk/capture.cpp trunk/channels.cpp trunk/channels.h trunk/epg.cpp trunk/epgfilter.cpp trunk/epgfilter.h trunk/grabber.cpp trunk/graph.cpp trunk/graph.h trunk/ini.cpp trunk/ini.h trunk/internet.cpp trunk/internet.h trunk/main.cpp trunk/main.h trunk/mpeg2defs.cpp trunk/mpeg2defs.h trunk/network.cpp trunk/parse.cpp trunk/pmtfilter.cpp trunk/pmtfilter.h trunk/record.cpp trunk/recprog.cpp trunk/recprog.h trunk/rendering.cpp trunk/res.rc trunk/resource.h trunk/search.cpp trunk/search.h trunk/settings.cpp trunk/trayicon.cpp trunk/update.cpp trunk/utils.cpp trunk/utils.h trunk/xml.cpp trunk/xml.h Log: Finalisation des transformations de compatibilité TCHAR : * À peu près toutes les corrections possibles sont faites et vérifiées. * Le projet peut maintenant se compiler indifféremment en mode 8 bits et Unicode et s'exécuter correctement dans les deux modes. * Noter que j'ai fini par trouver un aménagement qui permet de stocker la plupart des noms de filtres dans des chaînes TCHAR. Il reste cependant quelques exceptions, signalées en commentaires. Pouchin TV.sln, Pouchin TV.vcproj : * Ajout des configurations Debug_SBCS et Release_SBCS (SBCS = Single Byte Character Set) permettant de compiler le projet avec des caractères simple octet. * Ces configurations se connectent au projet "BaseClasses" en mode Debug_MBCS ou Release_MBCS, ce qui en la circonstance ne devrait pas poser de problèmes. * Ces configurations se connectent au projet "tinyxml" en mode Debug ou Release (sachant que dans ce projet, ces modes correspondent actuellement au mode SBCS, et que la configuration Unicode devait déjà s'y adapter). graph.cpp : * Ajout des fonctions d'assistance "AddFilterToGraph" pour gérer les ajouts de filtres et ne plus dépendre du type de caractères utilisé pour les noms de filtres. utils.h, utils.cpp : * Ajout des fonctions utilitaires "strlen_T" et "strcat_T', qui se joignent aux fonctions "strcpy_T" précédemment ajoutées, pour un usage analogue. * Ajout d'un typedef "tstring" pour introduire l'utilisation à venir de chaînes de caractères "string" ou "wstring" de la bibliothèques STL, lesquelles dans de nombreux cas gagneraient à être utilisées plutôt que de faire des allocations "malloc/free" ou "new/delete" pour des chaînes de caractères (note : limiter quand même l'usage de ceci aux cas où c'est nécessaire). * Ajout d'une macro STK_ALLOC (exploitant la fonction système "_alloca") pour allouer des tableaux de taille dynamiquement calculée, à utiliser pour les allocations de mémoire raisonnablement petites et dont la durée de vie est limitée à un corps de fonction. * Ajout d'une macro COPY_STR_ON_STACK (exploitant STK_ALLOC) pour effectuer des copies de chaînes de caractères (avec transformation de largeur de caractères éventuelle) dont la durée de vie est limitée à un corps de fonction. * Quelques réorganisations dans les fonctions "ConvertUTF82Char", notamment en raison du fait qu'en configuration SBCS, l'une d'entre elle venait à s'appeler elle-même, amenant un plantage pour cause de débordement de pile. ini.h, ini.cpp : * Réactivation de la sauvegarde des informations de pistes audio et vidéo (à cause des problèmes posés avec les enregistrements programmés). On peut cependant continuer à tester en mettant à zéro la macro STREAMS_SAVE_ALL. * La structure "RcdataResource" et la fonction "ExtraitRcdataResource" sont remplacées par une classe "RcdataResource" avec constructeur, destructeur et une méthode "Extraction". * Ceci est exploité notamment dans "cree_fichier_scan", permettant de ne plus avoir de "goto" dans cette fonction. * Correction de bug : dans la fonction "lit_chaines", suppression du "ZeroMemory" sur l'objet "canal" (cet objet était déjà initialisée par constructeur, avec des valeurs pas toutes égales à zéro, et le "ZeroMemory" écrasait ces valeurs, avec pour effet indirect de générer de nombreuses réécritures inutiles du fichier "chaines.xml"). Exploitation de ces nouvelles fonctions et macros à de nombreux endroits du code (parfois juste pour en améliorer la lisibilité, et aussi, dans le cas des strlen_T, pour tirer parti du fait que ces fonctions retournent une valeur UINT plutôt que size_t et donc éviter des "casts" de type). À plusieurs endroits du code, remplacement de types "size_t" par UINT, essentiellement pour éviter des avertissements de compilation en configuration x64. À plusieurs endroits du code, ajout du déclarateur "static" à des fonctions utilisées seulement localement dans le même fichier source. Un peu plus de commentaires de documentation, comme d'habitude ... Modifié: trunk/LCD.cpp =================================================================== --- trunk/LCD.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/LCD.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -247,13 +247,13 @@ // Programme actuel gauche SelectObject(this->m_hdc, this->m_police_heure); - TextOutA(this->m_hdc, 1, tm.tmHeight + 2, this->programmes[0].heure, (int)strlen(this->programmes[0].heure)); + TextOut(m_hdc, 1, tm.tmHeight + 2, programmes[0].heure, strlen_T(programmes[0].heure)); SelectObject(this->m_hdc, this->m_police); TextOutA(this->m_hdc, tm.tmAveCharWidth * 8, tm.tmHeight + 1, this->programmes[0].prog, (int)strlen(this->programmes[0].prog)); // Programme suivant gauche SelectObject(this->m_hdc, this->m_police_heure); - TextOutA(this->m_hdc, 1, (tm.tmHeight + 1)*2+1, this->programmes[1].heure, (int)strlen(this->programmes[1].heure)); + TextOut(m_hdc, 1, (tm.tmHeight + 1)*2+1, programmes[1].heure, strlen_T(programmes[1].heure)); SelectObject(this->m_hdc, this->m_police); TextOutA(this->m_hdc, tm.tmAveCharWidth * 8, (tm.tmHeight + 1)*2, this->programmes[1].prog, (int)strlen(this->programmes[1].prog)); } @@ -314,9 +314,9 @@ void CLcd::SetSuivant(){ if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici - strcpy_s(this->programmes[0].heure, _countof(this->programmes[0].heure), this->programmes[1].heure); - ZeroMemory(this->programmes[1].heure, sizeof(this->programmes[1].heure)); + strcpy_T(programmes[0].heure, programmes[1].heure); + ZeroMemory(programmes[1].heure, sizeof(programmes[1].heure)); - strcpy_s(this->programmes[0].prog, _countof(this->programmes[0].prog), this->programmes[1].prog); - ZeroMemory(this->programmes[1].prog, sizeof(this->programmes[1].prog)); + strcpy_T(programmes[0].prog, programmes[1].prog); + ZeroMemory(programmes[1].prog, sizeof(programmes[1].prog)); } Modifié: trunk/LCD.h =================================================================== --- trunk/LCD.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/LCD.h 2009-01-10 16:58:21 UTC (rev 163) @@ -55,7 +55,7 @@ /// Définit les programmes (actuel et suivant) struct { /// heure de début de diffusion - char heure[32]; + TCHAR heure[32]; /// nom du programme char prog[256]; } programmes[2]; Modifié: trunk/Pouchin TV.sln =================================================================== --- trunk/Pouchin TV.sln 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/Pouchin TV.sln 2009-01-10 16:58:21 UTC (rev 163) @@ -12,52 +12,64 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_SBCS|Win32 = Debug_SBCS|Win32 + Debug_SBCS|x64 = Debug_SBCS|x64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Release_SBCS|Win32 = Release_SBCS|Win32 + Release_SBCS|x64 = Release_SBCS|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Debug_SBCS|Win32.ActiveCfg = Debug_SBCS|Win32 + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Debug_SBCS|Win32.Build.0 = Debug_SBCS|Win32 + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Debug_SBCS|x64.ActiveCfg = Debug_SBCS|x64 + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Debug_SBCS|x64.Build.0 = Debug_SBCS|x64 {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Debug|Win32.ActiveCfg = Debug|Win32 {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Debug|Win32.Build.0 = Debug|Win32 {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Debug|x64.ActiveCfg = Debug|x64 {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Debug|x64.Build.0 = Debug|x64 + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Release_SBCS|Win32.ActiveCfg = Release_SBCS|Win32 + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Release_SBCS|Win32.Build.0 = Release_SBCS|Win32 + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Release_SBCS|x64.ActiveCfg = Release_SBCS|x64 + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Release_SBCS|x64.Build.0 = Release_SBCS|x64 {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Release|Win32.ActiveCfg = Release|Win32 {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Release|Win32.Build.0 = Release|Win32 {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Release|x64.ActiveCfg = Release|x64 {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}.Release|x64.Build.0 = Release|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_SBCS|Win32.ActiveCfg = Debug_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_SBCS|Win32.Build.0 = Debug_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_SBCS|x64.ActiveCfg = Debug_MBCS|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_SBCS|x64.Build.0 = Debug_MBCS|x64 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.ActiveCfg = Debug|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.Build.0 = Debug|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.ActiveCfg = Debug|x64 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.Build.0 = Debug|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_SBCS|Win32.ActiveCfg = Release_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_SBCS|Win32.Build.0 = Release_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_SBCS|x64.ActiveCfg = Release_MBCS|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_SBCS|x64.Build.0 = Release_MBCS|x64 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.ActiveCfg = Release|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.Build.0 = Release|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.ActiveCfg = Release|x64 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.Build.0 = Release|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Debug|Win32.ActiveCfg = Debug|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Debug|Win32.Build.0 = Debug|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Debug|x64.ActiveCfg = Debug|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Debug|x64.Build.0 = Debug|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Release|Win32.ActiveCfg = Release|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Release|Win32.Build.0 = Release|Win32 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Release|x64.ActiveCfg = Release|x64 - {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Release|x64.Build.0 = Release|x64 + {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Debug_SBCS|Win32.ActiveCfg = Debug|Win32 + {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Debug_SBCS|Win32.Build.0 = Debug|Win32 + {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Debug_SBCS|x64.ActiveCfg = Debug|x64 + {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Debug_SBCS|x64.Build.0 = Debug|x64 {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Debug|Win32.ActiveCfg = Debug|Win32 {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Debug|Win32.Build.0 = Debug|Win32 {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Debug|x64.ActiveCfg = Debug|x64 {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Debug|x64.Build.0 = Debug|x64 + {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Release_SBCS|Win32.ActiveCfg = Release|Win32 + {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Release_SBCS|Win32.Build.0 = Release|Win32 + {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Release_SBCS|x64.ActiveCfg = Release|x64 + {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Release_SBCS|x64.Build.0 = Release|x64 {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Release|Win32.ActiveCfg = Release|Win32 {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Release|Win32.Build.0 = Release|Win32 {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Release|x64.ActiveCfg = Release|x64 {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Release|x64.Build.0 = Release|x64 - {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Vista Debug|Win32.ActiveCfg = Debug|Win32 - {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Vista Debug|Win32.Build.0 = Debug|Win32 - {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Vista Debug|x64.ActiveCfg = Debug|x64 - {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Vista Debug|x64.Build.0 = Debug|x64 - {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Vista Release|Win32.ActiveCfg = Release|Win32 - {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Vista Release|Win32.Build.0 = Release|Win32 - {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Vista Release|x64.ActiveCfg = Release|x64 - {C406DAEC-0886-4771-8DEA-9D7329B46CC1}.Vista Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/Pouchin TV.vcproj 2009-01-10 16:58:21 UTC (rev 163) @@ -67,11 +67,11 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + last_pcr) last_pcr = new_pcr; - //myprintf(L"TS pcr = %10.6f (ajusté = %10.6f)\n", + //myprintf(TEXT("TS pcr = %10.6f (ajusté = %10.6f)\n"), // new_pcr/27000000.0, (new_pcr-first_pcr)/27000000.0); } } Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/channels.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -42,7 +42,7 @@ // Taille des images des chaînes (largeur et longueur) #define TAILLE_IMAGE_CHAINE 16 -HBITMAP cherche_icone(LPCTSTR dir, LPCSTR nom) +static HBITMAP cherche_icone(LPCTSTR dir, LPCTSTR nom) { TCHAR pathName[MAX_PATH], fileName[MAX_PATH]; @@ -50,7 +50,7 @@ LPTSTR szChemin = NULL; // Concaténation chemin et chaîne - _stprintf_s(fileName, _countof(fileName), TEXT("%") A2t TEXT(".bmp"), nom); + _stprintf_s(fileName, _countof(fileName), TEXT("%s.bmp"), nom); _stprintf_s(pathName, _countof(pathName), TEXT("%s\\Icones\\"), dir); if (FindFileRecur(pathName, fileName, &szChemin)) { @@ -154,7 +154,7 @@ /** * Charge les bitmaps des chaînes **/ - NomProtege nom_canal(nom, '_'); + NomProtege nom_canal(nom, '_'); hImage = cherche_icone(pouchindir_conf, nom_canal.nom); Modifié: trunk/channels.h =================================================================== --- trunk/channels.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/channels.h 2009-01-10 16:58:21 UTC (rev 163) @@ -34,8 +34,8 @@ UINT16 eid; // "event id" SYSTEMTIME debut; SYSTEMTIME fin; - char nom[86]; - char desc[256]; + TCHAR nom[86]; + TCHAR desc[256]; Emission() { ZeroMemory(this, sizeof(*this));} @@ -78,7 +78,7 @@ /// Structure décrivant une fréquence struct Frequence { UINT16 canal_no; ///< numéro du canal (de 1 à 60) - long khz; ///< fréquence (canal convertis en khz) + long khz; ///< fréquence (canal converti en khz) Frequence() : canal_no(0), @@ -102,23 +102,27 @@ HBITMAP hImage; public: // - // Constructeur : + /// Constructeur Chaine(); - // + + /// Chargement de l'icône associée à la chaîne + /// \todo Le chargement de l'icône (pourtant existante) dans le menu échoue + /// parfois, de façon apparemment aléatoire. Chercher pourquoi. HBITMAP ChargeIcone(); - // - // Fonction retournant 'true' si cette chaîne a un rang supérieur de classement - // à celui de la chaîne 'canal2'. + + /// Fonction retournant \p true si cette chaîne a un rang supérieur de classement + /// à celui de la chaîne 'canal2'. bool compare(const Chaine & canal2) const // inline { return numeroChaine > canal2.numeroChaine || (numeroChaine == canal2.numeroChaine && _stricmp(nom, canal2.nom) > 0); } - // Génération du nom affichable pour le menu + + /// Génération du nom affichable pour le menu int toMenuString(LPTSTR pstr, size_t bufSize) const; - // Mappage de tous les PIDs de la chaîne (la fréquence est présumée déjà syntonisée) ; - // Si 'reset_son' est 'true', alors le canal son est, en même temps, remis à sa - // valeur par défaut, selon préférences globales de l'utilisateur : + /// Mappage de tous les PIDs de la chaîne (la fréquence est présumée déjà syntonisée) ; + /// Si \p reset_son est \p true, alors le canal son est, en même temps, remis à sa + /// valeur par défaut, selon préférences globales de l'utilisateur : HRESULT branche(bool reset_son) const; }; Modifié: trunk/epg.cpp =================================================================== --- trunk/epg.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/epg.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -57,37 +57,39 @@ if (emis.cle == 0) return; - LVITEMA item = { + COPY_STR_ON_STACK(TCHAR, canal_nom, canal.nom, taille); + + LVITEM item = { LVIF_TEXT | LVIF_PARAM, // mask iItem, // iItem EPG_COL_CHAINE, // iSubItem 0, 0, // state, stateMask - const_cast(canal.nom), // pszText + canal_nom, // pszText 0, // cchTextMax 0, // iImage MAKELPARAM(canal.SID, noEmis) // lParam }; - CHAR str[16]; + TCHAR str[16]; - SendMessage(hListItem, LVM_INSERTITEMA, 0, (LPARAM)&item); + SendMessage(hListItem, LVM_INSERTITEM, 0, (LPARAM)&item); - item.pszText = const_cast(str); + item.pszText = const_cast(str); TimeToStr(emis.debut, str, _countof(str)); item.iSubItem = EPG_COL_DEBUT; - SendMessage(hListItem, LVM_SETITEMTEXTA, iItem, (LPARAM)&item); + SendMessage(hListItem, LVM_SETITEMTEXT, iItem, (LPARAM)&item); TimeToStr(emis.fin, str, _countof(str)); item.iSubItem = EPG_COL_FIN; - SendMessage(hListItem, LVM_SETITEMTEXTA, iItem, (LPARAM)&item); + SendMessage(hListItem, LVM_SETITEMTEXT, iItem, (LPARAM)&item); - item.pszText = const_cast(emis.nom); + item.pszText = const_cast(emis.nom); item.iSubItem = EPG_COL_PROGRAMME; - SendMessage(hListItem, LVM_SETITEMTEXTA, iItem, (LPARAM)&item); + SendMessage(hListItem, LVM_SETITEMTEXT, iItem, (LPARAM)&item); - item.pszText = const_cast(emis.desc); + item.pszText = const_cast(emis.desc); item.iSubItem = EPG_COL_DESCRIPT; - SendMessage(hListItem, LVM_SETITEMTEXTA, iItem, (LPARAM)&item); + SendMessage(hListItem, LVM_SETITEMTEXT, iItem, (LPARAM)&item); iItem++; } Modifié: trunk/epgfilter.cpp =================================================================== --- trunk/epgfilter.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/epgfilter.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -34,7 +34,7 @@ #include "mpeg2defs.h" CEPGFilter::CEPGFilter(IUnknown *pUnk, HRESULT *phr) : - CBaseRenderer(__uuidof(this), szFilterName, pUnk, phr) + CBaseRenderer(__uuidof(this), WCHAR2TCHAR(szFilterName), pUnk, phr) { myprintf(TEXT("%") W2t TEXT(" construit\n"), szFilterName); } @@ -46,11 +46,11 @@ // Nettoyage des codes spéciaux (codes 0x80 à 0x9f) dans la chaîne, // ainsi que des espaces de début, de fin et multiples : -void clean_epg_string(LPSTR str) +void clean_epg_string(LPTSTR str) { - LPSTR src = str; - LPSTR dst = str; - UINT8 ch; // non signé ! + LPTSTR src = str; + LPTSTR dst = str; + UINT ch; // non signé ! while ((ch=*src++) != 0) { if (ch==DCTL_CRLF_A || ch=='\t') @@ -61,7 +61,7 @@ ) continue; - *dst++ = ch; + *dst++ = (TCHAR)ch; } // Enlever les espaces de fin : @@ -70,7 +70,7 @@ *dst = 0; } -LPCTSTR CEPGFilter::szFilterName = TEXT("Filtre EPG PTvM"); +LPCWSTR CEPGFilter::szFilterName = L"Filtre EPG PTvM"; CUnknown * WINAPI CEPGFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr) // static { @@ -165,7 +165,7 @@ const SI_EIT * peit; size_t taille = pMediaSample->GetActualDataLength(); -// myprintf(L"DoRenderSample %i %i\n", taille, p[0]); +// myprintf(TEXT("DoRenderSample %i %i\n"), taille, p[0]); pMediaSample->GetPointer((LPBYTE *)(&peit)); if ( Modifié: trunk/epgfilter.h =================================================================== --- trunk/epgfilter.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/epgfilter.h 2009-01-10 16:58:21 UTC (rev 163) @@ -40,6 +40,6 @@ HRESULT DoRenderSample(IMediaSample *pMediaSample); HRESULT CheckMediaType(const CMediaType *pmt); - static LPCWSTR szFilterName; - static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr); + static LPCWSTR szFilterName; // Ne PAS convertir en LPCTSTR (TCHAR) + static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr); }; Modifié: trunk/grabber.cpp =================================================================== --- trunk/grabber.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/grabber.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -44,7 +44,7 @@ BYTE * p; long l = pSample->GetActualDataLength(); - //myprintf(L"taille %i\n", l); + //myprintf(TEXT("taille %i\n"), l); pSample->GetPointer(&p); Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/graph.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -103,6 +103,32 @@ #endif // #if EXPORT_GRAPH +/** + * Ajout d'un filtre au graphe + * + * \param[in] pFilter Filtre à ajouter + * \param[in] pszName Nom de ce filtre + **/ +static inline HRESULT AddFilterToGraph(IBaseFilter * pFilter, LPCWSTR pszName) +{ + return pGraph->AddFilter(pFilter, pszName); +} + +#ifndef _UNICODE +/** + * Ajout d'un filtre au graphe (version CHAR 8 bits) + * + * \param[in] pFilter Filtre à ajouter + * \param[in] pszName Nom de ce filtre + **/ +static HRESULT AddFilterToGraph(IBaseFilter * pFilter, LPCSTR pszName) +{ + COPY_STR_ON_STACK(WCHAR, pszTmp, pszName, nLen); + + return AddFilterToGraph(pFilter, pszTmp); +} +#endif + void clean_dshow(void) { myprintf(TEXT("save ok\n")); @@ -175,25 +201,25 @@ * \param[in] nom Nom à associer à ce filtre * \param[out] pFilter Interface renvoyée de ce filtre **/ -HRESULT create_and_add_filter(REFCLSID clsid, LPCWSTR nom, +HRESULT create_and_add_filter(REFCLSID clsid, LPCTSTR nom, CComPtr & pFilter) { HRESULT hr = pFilter.CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER); if (FAILED(hr)) - return erreur(TEXT("Le filtre \"%") W2t TEXT("\" n'a pas pu être créé"), hr, nom); + return erreur(TEXT("Le filtre \"%s\" n'a pas pu être créé"), hr, nom); - hr = pGraph->AddFilter(pFilter, nom); + hr = AddFilterToGraph(pFilter, nom); if (FAILED(hr)) - return erreur(TEXT("Le filtre \"%") W2t TEXT("\" n'a pas pu être ajouté au graphe"), hr, nom); + return erreur(TEXT("Le filtre \"%s\" n'a pas pu être ajouté au graphe"), hr, nom); return hr; } // Création et ajout d'un filtre de type codec défini par son nom, et devant // de plus correspondre au type 'type' et au sous-type 'subtype' définis. -static HRESULT get_and_add_codec(LPCWSTR nom, GUID type, GUID subtype, +static HRESULT get_and_add_codec(LPCTSTR nom, GUID type, GUID subtype, LPCTSTR infotype, CComPtr & pFilter) { HRESULT hr = CSearchByType_Get(type, subtype, exact_match, nom, pFilter).Do(); @@ -201,9 +227,9 @@ if (SUCCEEDED(hr)) { myprintf(TEXT("Ajout codec %s\n"), infotype); - hr = pGraph->AddFilter(pFilter, nom); + hr = AddFilterToGraph(pFilter, nom); if (FAILED(hr)) - return erreur(TEXT("Le codec %s \"%") W2t TEXT("\" n'a pas pu être inséré dans le graphe"), + return erreur(TEXT("Le codec %s \"%s\" n'a pas pu être inséré dans le graphe"), hr, infotype, nom); } return hr; @@ -389,7 +415,7 @@ hr = connect_pin_to_filter(pVideoPin, pVideoCodec); if (FAILED(hr)) return erreur( - TEXT("Impossible de connecter le démultiplexeur au codec vidéo MPEG2 \"%") W2t TEXT("\""), + TEXT("Impossible de connecter le démultiplexeur au codec vidéo MPEG2 \"%s\""), hr, filtreMPEG2); } else { #if AUTO_RENDER @@ -438,7 +464,7 @@ return erreur(TEXT("La broche audio MPEG2 n'a pas pu être créée"), hr); // add direct sound - hr = create_and_add_filter(CLSID_DSoundRender, L"DirectSound (MPEG2)", pDSound); + hr = create_and_add_filter(CLSID_DSoundRender, TEXT("DirectSound (MPEG2)"), pDSound); if (FAILED(hr)) return hr; @@ -449,13 +475,13 @@ hr = connect_pin_to_filter(pSoundPin, pAudioCodec); if (FAILED(hr)) return erreur( - TEXT("Impossible de connecter le démultiplexeur au codec audio MPEG2 \"%") W2t TEXT("\""), + TEXT("Impossible de connecter le démultiplexeur au codec audio MPEG2 \"%s\""), hr, filtreAudio); hr = connect_filters(pAudioCodec, pDSound); if (FAILED(hr)) return erreur( - TEXT("Impossible de connecter le Codec audio MPEG2 \"%") W2t TEXT("\" au filtre de rendu DirectSound"), + TEXT("Impossible de connecter le Codec audio MPEG2 \"%s\" au filtre de rendu DirectSound"), hr, filtreAudio); } else { @@ -504,7 +530,7 @@ return erreur(TEXT("La broche audio AC3 n'a pas pu être créée"), hr); // add direct sound - hr = create_and_add_filter(CLSID_DSoundRender, L"DirectSound (AC3)", pDSoundAc3); + hr = create_and_add_filter(CLSID_DSoundRender, TEXT("DirectSound (AC3)"), pDSoundAc3); if (FAILED(hr)) return hr; @@ -515,13 +541,13 @@ hr = connect_pin_to_filter(pAc3Pin, pAc3Codec); if (FAILED(hr)) return erreur( - TEXT("Impossible de connecter le démultiplexeur au codec AC3 \"%") W2t TEXT("\""), + TEXT("Impossible de connecter le démultiplexeur au codec AC3 \"%s\""), hr, filtreAc3); hr = connect_filters(pAc3Codec, pDSoundAc3); if (FAILED(hr)) return erreur( - TEXT("Impossible de connecter le Codec audio AC3 \"%") W2t TEXT("\" au filtre de rendu DirectSound"), + TEXT("Impossible de connecter le Codec audio AC3 \"%s\" au filtre de rendu DirectSound"), hr, filtreAc3); } else { #if AUTO_RENDER @@ -564,7 +590,7 @@ { CComPtr pPSIFilter; - hr = create_and_add_filter(__uuidof(Mpeg2Data), L"MPEG-2 Sections and Tables", pPSIFilter); + hr = create_and_add_filter(__uuidof(Mpeg2Data), TEXT("MPEG-2 Sections and Tables"), pPSIFilter); if (FAILED(hr)) return hr; @@ -615,7 +641,7 @@ if (FAILED(hr)) return erreur(TEXT("Le filtre EPG n'a pas pu être créé"), hr); - hr = pGraph->AddFilter(pEPGFilter, CEPGFilter::szFilterName); + hr = AddFilterToGraph(pEPGFilter, CEPGFilter::szFilterName); if (FAILED(hr)) return erreur(TEXT("Le filtre EPG n'a pas pu être ajouté au graphe"), hr); @@ -663,7 +689,7 @@ if (FAILED(hr)) return erreur(TEXT("Le filtre PMT n'a pas pu être créé"), hr); - hr = pGraph->AddFilter(pPMTFilter, CPMTFilter::szFilterName); + hr = AddFilterToGraph(pPMTFilter, CPMTFilter::szFilterName); if (FAILED(hr)) return erreur(TEXT("Le filtre PMT n'a pas pu être ajouté au graphe"), hr); @@ -866,7 +892,7 @@ dynamic_cast(CNetworkProvider::CreateInstance(NULL, &hr)); if (SUCCEEDED(hr)) - hr = pGraph->AddFilter(pNetworkProvider, CNetworkProvider::szFilterName); + hr = AddFilterToGraph(pNetworkProvider, CNetworkProvider::szFilterName); if (FAILED(hr)) return erreur(TEXT("Échec de l'insertion du filtre Network Provider"), hr); @@ -878,11 +904,11 @@ if (eCompat == compat_Tuner) { // PCI - hr = pGraph->AddFilter(pNetworkTuner, nom_tuner); + hr = AddFilterToGraph(pNetworkTuner, nom_tuner); if (FAILED(hr)) return erreur(TEXT("Échec de l'insertion du filtre Tuner"), hr); - hr = pGraph->AddFilter(pReceiverComponent, nom_receiver); + hr = AddFilterToGraph(pReceiverComponent, nom_receiver); if (FAILED(hr)) return erreur(TEXT("Échec de l'insertion du filtre Récepteur"), hr); @@ -901,7 +927,7 @@ // USB // connect USB - hr = pGraph->AddFilter(pNetworkTuner, nom_tuner); + hr = AddFilterToGraph(pNetworkTuner, nom_tuner); if (FAILED(hr)) return erreur(TEXT("Échec de l'insertion du filtre Tuner USB"), hr); @@ -928,9 +954,9 @@ CComPtr filtrePrec = pAvantDemux; for (int i=0; i pGrabber; - WCHAR nom[20]; + TCHAR nom[20]; - swprintf_s(nom, _countof(nom), L"Grabber %u", i); + _stprintf_s(nom, _countof(nom), TEXT("Grabber %u"), i); hr = create_and_add_filter(CLSID_SampleGrabber, nom, pGrabber); if (FAILED(hr)) return hr; @@ -948,7 +974,7 @@ // connect 4 - hr = create_and_add_filter(CLSID_MPEG2Demultiplexer, L"MPEG2 Demultiplexer", pDemux); + hr = create_and_add_filter(CLSID_MPEG2Demultiplexer, TEXT("MPEG2 Demultiplexer"), pDemux); if (FAILED(hr)) return hr; Modifié: trunk/graph.h =================================================================== --- trunk/graph.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/graph.h 2009-01-10 16:58:21 UTC (rev 163) @@ -111,5 +111,5 @@ * \param[in] nom Nom à associer à ce filtre * \param[out] pFilter Interface renvoyée de ce filtre **/ -HRESULT create_and_add_filter(REFCLSID clsid, LPCWSTR nom, +HRESULT create_and_add_filter(REFCLSID clsid, LPCTSTR nom, CComPtr & pFilter); \ Pas de fin de ligne à la fin du fichier Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/ini.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -351,7 +351,7 @@ * \param[in] prefixe2 nom de la chaîne enregistrée * \param[in] extension extension du fichier (permet de définir le type du fichier (BMP, MPG, TS, ...) **/ -NomFichierAvecDate::NomFichierAvecDate(LPCTSTR dir, LPCSTR prefixe1, LPCSTR prefixe2, LPCTSTR extension) +NomFichierAvecDate::NomFichierAvecDate(LPCTSTR dir, LPCTSTR prefixe1, LPCSTR prefixe2, LPCTSTR extension) { // Remplace les caractères invalides par des espaces NomProtege prefix_prot1(prefixe1, TCHAR(' ')); @@ -488,23 +488,17 @@ } /** - * Extrait une resource de type RCData du fichier - * - * Paramètres: - * LPCWSTR nom_resource: nom de la resource. Utiliser MAKEINTRESOURCE pour des entiers. - * RcdataResource: chaîne contenant le retour. Initialisé par la fonction. - * La taille du tableau aussi; - * Ne pas oublier de faire un delete une fois utilisé... - * - * Retour: - * 1 en cas de succes - * 0 en cas d'échec + * Extrait une resource de type RCData du fichier. Charge également la taille allouée. + * \param[in] idRessource Identifiant de la resource. + * \retval \p true en cas de succès, \p false en cas d'échec. **/ -int ExtraitRcdataResource(LPCWSTR nom_resource, RcdataResource *resource) { - HRSRC hRcdataResource = FindResource(hAppInstance, nom_resource, RT_RCDATA); +bool RcdataResource::Extraction(UINT idRessource) +{ + HRSRC hRcdataResource = FindResource(hAppInstance, MAKEINTRESOURCE(idRessource), RT_RCDATA); + bool bRes = false; if (hRcdataResource != NULL) { - resource->taille = SizeofResource(hAppInstance, hRcdataResource); + taille = SizeofResource(hAppInstance, hRcdataResource); // Charge la ressource identifiée HGLOBAL hRcdataCharge = LoadResource(hAppInstance, hRcdataResource); @@ -512,26 +506,24 @@ // Bloque la ressource en mémoire pour utilisation LPBYTE RcdataRes = (LPBYTE)LockResource(hRcdataCharge); - if (RcdataRes != NULL) { + if (RcdataRes == NULL) { // Tout s'est bien passé: on peut utiliser la resource - resource->contenu = new BYTE[resource->taille + 1]; - ZeroMemory(resource->contenu, resource->taille + 1); - for (int i=0; itaille; i++) - resource->contenu[i] = RcdataRes[i]; - } else - return 0; + contenu = new BYTE[taille + 1]; + ZeroMemory(contenu, taille + 1); + for (int i=0; i vers_ini) - goto extract; - else - goto fin; + if (vers_res <= vers_ini) + return; + } - } else - return; + FILE * fop; -extract: - if (_tfopen_s(&fop, fileName, TEXT("wb"))) { + if (_tfopen_s(&fop, fileName, TEXT("wb"))) myprintf(TEXT("Fichier canaux.ini => Erreur écriture\n")); - } else { + else { myprintf(TEXT("Fichier canaux.ini => Création\n")); - fputs((LPCSTR)canaux.contenu, fop); + fputs(canaux, fop); fclose(fop); } - -fin: - delete [] canaux.contenu; } /** @@ -686,7 +672,7 @@ * \param[out] stim date/heure lue * \param[in] xstn XMLSystemTimeNames contenant le nom des éléments à interroger **/ -void xmlLoadSystemTime(CXMLNode * pNode, SYSTEMTIME & stim, const XMLSystemTimeNames & xstn) +static void xmlLoadSystemTime(CXMLNode * pNode, SYSTEMTIME & stim, const XMLSystemTimeNames & xstn) { stim.wYear = (WORD)pNode->getInt(xstn.name_wYear); stim.wMonth = (WORD)pNode->getInt(xstn.name_wMonth); @@ -838,7 +824,7 @@ * \param[in] section nom du noeud * \param[in] stim date à enregistrer **/ -void xmlSaveSystemTime(CXMLOutput & oxml, LPCSTR section, const SYSTEMTIME & stim) +static void xmlSaveSystemTime(CXMLOutput & oxml, LPCSTR section, const SYSTEMTIME & stim) { CXMLOpenChild oxmlc(oxml, section); @@ -900,19 +886,18 @@ /** * Chargement du fichier des chaînes "chaines.xml". * - * \retval 0 en cas de succès - * \retval 1 si erreur + * \retval S_OK en cas de succès + * \retval S_FAILED (ou autre) si erreur **/ -int lit_chaines() +HRESULT lit_chaines() { // Fichier XML CXMLWrapper xml; HRESULT hr = xml.charge(NomFichierConf(TEXT("chaines.xml"))); - if (FAILED(hr)) { - return 1; - } + if (hr!=S_OK) + return hr; // Récupère le noeud racine CXMLElement root = xml.getDocElement(); @@ -926,8 +911,11 @@ CXMLNode * pNode = children[i]; Chaine canal; - ZeroMemory(&canal, sizeof(Chaine)); + // ZeroMemory(&canal, sizeof(Chaine)); + // # supprimé car (1) "canal" est déjà initialisé par son constructeur et + // # (2) les valeurs d'initialisation qu'il contient ne sont pas toutes des zéros. + pNode->getStr(TEXT("Nom"), canal.nom, _countof(canal.nom)); canal.canal_no = (WORD)pNode->getInt(TEXT("Canal")); pNode->getStr(TEXT("Groupe"), canal.groupe, _countof(canal.groupe)); @@ -949,8 +937,8 @@ canal.pmt_pid = (WORD)pNode->getInt(TEXT("PMT")); canal.pcr_pid = (WORD)pNode->getInt(TEXT("PCR")); -// Désactivation des informations sur les flux vidéo, son et autre -#if 0 +// Désactivation optionnelle des informations sur les flux vidéo, son et autre +#if STREAMS_SAVE_ALL // Détermine le type de flux vidéo if ((canal.video_pid = (UINT16)pNode->getInt(TEXT("Video")))!=0) canal.video_type = vst_MPEG2; @@ -992,11 +980,11 @@ delete pNode; } - return 0; + return S_OK; } /** - * Mémorise la liste des chaînes + * Sauvegarde de la liste des chaînes dans "chaines.xml". **/ void sauve_chaines(void) { @@ -1034,8 +1022,8 @@ oxml.put("PMT", canal.pmt_pid); oxml.put("PCR", canal.pcr_pid); -// Désactivation des informations sur les flux vidéos, son et autre -#if 0 +// Désactivation optionnelle des informations sur les flux vidéo, son et autre +#if STREAMS_SAVE_ALL // Mémorise le type de flux vidéo switch (canal.video_type) { @@ -1077,10 +1065,10 @@ * * \param[in] lpKeyName nom de la clé devant être utilisée * \param[in] lpString chaîne de caractères à enregistrer - * \retval "une valeur non nule" en cas de succès + * \retval "une valeur non nulle" en cas de succès * \retval 0 en cas d'erreur **/ -BOOL save_config_str(LPCTSTR lpKeyName, LPCTSTR lpString) +static BOOL save_config_str(LPCTSTR lpKeyName, LPCTSTR lpString) { return WritePrivateProfileString(ini_config, lpKeyName, lpString, confPathName); } @@ -1090,10 +1078,10 @@ * * \param[in] lpKeyName nom de la clé devant être utilisée * \param[in] value valeur numérique à enregistrer - * \retval "une valeur non nule" en cas de succès + * \retval "une valeur non nulle" en cas de succès * \retval 0 en cas d'erreur **/ -BOOL save_config_int(LPCTSTR lpKeyName, LONG value) +static BOOL save_config_int(LPCTSTR lpKeyName, LONG value) { TCHAR valeur[64]; @@ -1105,12 +1093,12 @@ * Écriture de la chaîne de caractères associée à une valeur fournie * * \param[in] lpKeyName nom de la clé devant être utilisée - * \param[in] assocTable AssocElement contenant le tableau à traduire - * \param[in] value valeur numérique devant être converti en chaine de caractères - * \retval "une valeur non nule" en cas de succès + * \param[in] assocTable \p AssocElement contenant le tableau à traduire + * \param[in] value valeur numérique devant être convertie en chaine de caractères + * \retval "une valeur non nulle" en cas de succès * \retval 0 en cas d'erreur **/ -BOOL save_config_assoc(LPCTSTR lpKeyName, const AssocElement * assocTable, DWORD value) +static BOOL save_config_assoc(LPCTSTR lpKeyName, const AssocElement * assocTable, DWORD value) { return save_config_str(lpKeyName, dword2str(assocTable, value)); } @@ -1120,10 +1108,10 @@ * * \param[in] lpKeyName nom de la clé devant être utilisée * \param[in] value valeur à enregistrer - * \retval "une valeur non nule" en cas de succès + * \retval "une valeur non nulle" en cas de succès * \retval 0 en cas d'erreur **/ -BOOL save_config_bool(LPCTSTR lpKeyName, bool value) +static BOOL save_config_bool(LPCTSTR lpKeyName, bool value) { return save_config_assoc(lpKeyName, aBoolTable, value); } @@ -1136,7 +1124,7 @@ * \retval 0 en cas d'échec * \retval "toute autre valeur" en cas de succès **/ -BOOL save_config_winpos(LPCTSTR lpKeyName, HWND hWnd) +static BOOL save_config_winpos(LPCTSTR lpKeyName, HWND hWnd) { WINDOWPLACEMENT wpl; TCHAR position[32]; @@ -1152,7 +1140,7 @@ /** * Sauvegarde les raccourcis - */ + **/ void save_config_raccourcis(void) { for (size_t i=0; i<_countof(shortcuts); i++) { ShortcutItem &shortcut = shortcuts[i]; @@ -1240,13 +1228,13 @@ { // Récupère les dossiers de Pouchin TV Mod GetModuleFileName(NULL, pouchindir_prog, _countof(pouchindir_prog)); - for (size_t i = wcslen(pouchindir_prog) - 1; L'\\'!=pouchindir_prog[i]; i--) - pouchindir_prog[i] = L'\0'; + for (size_t i = strlen_T(pouchindir_prog) - 1; TCHAR('\\')!=pouchindir_prog[i]; i--) + pouchindir_prog[i] = TCHAR('\0'); // CSIDL_COMMON_APPDATA : ApplicationData partagé par tous // CSIDL_APPDATA : ApplicationData de l'utilisateur SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, pouchindir_conf); - _tcscat_s(pouchindir_conf, L"\\Pouchin TV Mod\\"); + _tcscat_s(pouchindir_conf, TEXT("\\Pouchin TV Mod\\")); // Place le répertoire courant sur le répertoire de Pouchin TV Mod SetCurrentDirectory(pouchindir_prog); @@ -1264,7 +1252,7 @@ * \param[in] lpDefault valeur par défaut, si on n'a rien trouvé * \return Nombre de caractères copiés, sans tenir compte du caractère '\\0' **/ -DWORD load_config_str(LPCTSTR lpKeyName, LPTSTR lpValue, DWORD bufSize, LPCTSTR lpDefault=TEXT("")) +static DWORD load_config_str(LPCTSTR lpKeyName, LPTSTR lpValue, DWORD bufSize, LPCTSTR lpDefault=TEXT("")) { return GetPrivateProfileString(ini_config, lpKeyName, lpDefault, lpValue, bufSize, confPathName); } @@ -1276,7 +1264,7 @@ * \param[in] nDefault valeur par défaut, si on n'a rien trouvé * \return valeur recherchée (trouvée, ou par défaut) **/ -UINT load_config_int(LPCTSTR lpKeyName, INT nDefault) +static UINT load_config_int(LPCTSTR lpKeyName, INT nDefault) { return GetPrivateProfileInt(ini_config, lpKeyName, nDefault, confPathName); } @@ -1289,7 +1277,7 @@ * \param[in] bydefault valeur par défaut, si on n'a rien trouvé * \return valeur recherchée (trouvée, ou par défaut) **/ -DWORD load_config_assoc(LPCTSTR lpKeyName, const AssocElement * assocTable, DWORD bydefault) +static DWORD load_config_assoc(LPCTSTR lpKeyName, const AssocElement * assocTable, DWORD bydefault) { TCHAR str[32]; @@ -1304,7 +1292,7 @@ * \param[in] bydefault valeur par défaut, si on n'a rien trouvé * \return valeur recherchée (trouvée, ou par défaut) **/ -bool load_config_bool(LPCTSTR lpKeyName, bool bydefault=false) +static bool load_config_bool(LPCTSTR lpKeyName, bool bydefault=false) { return load_config_assoc(lpKeyName, aBoolTable, bydefault)!=0; } @@ -1317,7 +1305,7 @@ * \param[in] defL largeur par défaut, si pas trouvé * \param[in] defH hauteur par défaut, si pas trouvé **/ -void load_config_winpos(LPCTSTR lpKeyName, WindowPos & wpos, long defL, long defH) +static void load_config_winpos(LPCTSTR lpKeyName, WindowPos & wpos, long defL, long defH) { TCHAR position[32]; @@ -1344,7 +1332,7 @@ * \warning Si le dossier désiré demandé par \a nDefaultFolder n'existe pas (parce que la version est trop vieille, ou autre), * celui-ci est remplacé par le dossier \c "Mes Documents" **/ -DWORD load_config_path(LPCTSTR lpKeyName, LPTSTR lpValue, DWORD bufSize, int nDefaultFolder) +static DWORD load_config_path(LPCTSTR lpKeyName, LPTSTR lpValue, DWORD bufSize, int nDefaultFolder) { TCHAR default_dir[MAX_PATH]; @@ -1364,9 +1352,9 @@ ACCEL accel[_countof(shortcuts)*2]; ZeroMemory(accel, sizeof(ACCEL)*_countof(shortcuts)*2); - size_t j=0; // index pour les accélérateurs + UINT j=0; // index pour les accélérateurs - for (size_t i=0; i<_countof(shortcuts); i++) { + for (UINT i=0; i<_countof(shortcuts); i++) { ShortcutItem & item = shortcuts[i]; // représente la ligne actuelle des valeurs par défaut TCHAR buffer[128], // Buffer temporaire de travail cle[32]; // Clé à questionner dans le fichier INI @@ -1440,27 +1428,28 @@ void load_config(void) { TCHAR chemin_config[MAX_PATH]; - _tcscpy_s(chemin_config, _countof(chemin_config), pouchindir_conf); - _tcscat_s(chemin_config, _countof(chemin_config), config_file); - _tcscpy_s(confPathName, _countof(confPathName), chemin_config); + strcpy_T(chemin_config, pouchindir_conf); + strcat_T(chemin_config, config_file); + strcpy_T(confPathName, chemin_config); + // Recherche si on a un fichier de config dans AppData load_config_str(ini_tuner, nom_tuner, _countof(nom_tuner)); - if (_tcscmp(nom_tuner, TEXT("")) == 0) { + if (nom_tuner[0] == 0) { // Pas de tuner trouvé. On recherche dans le dossier courant - _tcscpy_s(confPathName, _countof(confPathName), pouchindir_prog); - _tcscat_s(confPathName, _countof(confPathName), config_file); + strcpy_T(confPathName, pouchindir_prog); + strcat_T(confPathName, config_file); load_config_str(ini_tuner, nom_tuner, _countof(nom_tuner)); // Vérifie si on a une réponse - if(_tcscmp(nom_tuner, TEXT("")) == 0) + if (nom_tuner[0] == 0) // Comme fichier config.ini n'existe pas non plus, restauration du chemin vers %AppData% - _tcscpy_s(confPathName, _countof(confPathName), chemin_config); + strcpy_T(confPathName, chemin_config); else // la config du tuner a été trouvée dans le répertoire de PTVM // On change le répertoire de config vers celui du programme - _tcscpy_s(pouchindir_conf, _countof(pouchindir_conf), pouchindir_prog); + strcpy_T(pouchindir_conf, pouchindir_prog); } load_config_str(ini_receiver, nom_receiver, _countof(nom_receiver)); Modifié: trunk/ini.h =================================================================== --- trunk/ini.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/ini.h 2009-01-10 16:58:21 UTC (rev 163) @@ -30,6 +30,16 @@ #include "utils.h" #include "channels.h" +/** + * Activation (1) ou désactivation (0) de la sauvegarde des informations + * sur les flux vidéos, son et autre/ + * \test La désactivation semble poser problème, notamment vis à vis des + * enregistrements programmés. Pour le moment, laisser activé et ne se + * servir de ceci que pour des tests d'évolutions progressives visant à + * permettre une désactivation sûre. + **/ +#define STREAMS_SAVE_ALL 1 + /// Répertoire de Pouchin TV Mod extern TCHAR pouchindir_prog[MAX_PATH]; @@ -80,40 +90,44 @@ TCHAR str[MAX_PATH]; NomFichierConf(LPCTSTR pszBaseName) { - _tcscpy_s(str, pouchindir_conf); - _tcscat_s(str, pszBaseName); + strcpy_T(str, pouchindir_conf); + strcat_T(str, pszBaseName); } operator LPCTSTR() const { return str;} }; -/// Permet de décrire les fichiers inclus dans les resources de PTVM -struct RcdataResource { - int taille; ///< taille de la ressource concernée - LPBYTE contenu; ///< contenu de la ressource +/// Classe permettant de récupérer les fichiers inclus dans les resources de PTVM +class RcdataResource +{ +public: + int taille; ///< taille de la ressource concernée + LPBYTE contenu; ///< contenu de la ressource + + RcdataResource() : + taille(0), + contenu(NULL) + {} + + /** + * Extrait une resource de type RCData du fichier. Charge également la taille allouée. + * \param[in] idRessource Identifiant de la resource. + * \retval \p true en cas de succès, \p false en cas d'échec. + **/ + bool Extraction(UINT idRessource); + + operator LPCSTR() const { + return reinterpret_cast(contenu);} + + ~RcdataResource() { + if (contenu) + delete [] contenu; + } }; /** - * Extrait une resource de type RCData du fichier - * - * Paramètres: - * LPCWSTR nom_resource: nom de la resource. Utiliser MAKEINTRESOURCE pour des entiers. - * RcdataResource: chaîne contenant le retour. Initialisé par la fonction. - * La taille du tableau aussi; - * Ne pas oublier de faire un delete une fois utilisé... - * - * Retour: - * 1 en cas de succes - * 0 en cas d'échec - **/ -int ExtraitRcdataResource(LPCWSTR nom_resource, RcdataResource *resource); - -/** * Vérifie l'existence du fichier "canaux.ini", et le crée à partir des ressources * s'il n'existe pas. - * \todo Vérifier l'existence du fichier n'est pas suffisant. Il conviendrait de vérifier - * également sa version, afin que celui-ci soit mis à jour à chaque fois qu'une version de - * PouchinTv Mod qui en inclut une version plus récente est installée. **/ void cree_fichier_scan(); @@ -128,13 +142,13 @@ /** * Chargement du fichier des chaînes "chaines.xml". * - * \retval 0 en cas de succès - * \retval 1 si erreur + * \retval S_OK en cas de succès + * \retval S_FAILED (ou autre) si erreur **/ -int lit_chaines(); +HRESULT lit_chaines(); /** - * Mémorise la liste des chaînes + * Sauvegarde de la liste des chaînes dans "chaines.xml". **/ void sauve_chaines(void); @@ -176,22 +190,11 @@ /** * Sauvegarde les raccourcis - * \todo Considérer les améliorations suivantes, autant que possible avant la sortie - * de la version officielle, afin d'éviter d'avoir des utilisateurs qui perdent - * leur configuration, ou qui se retrouvent avec un configuration incorrecte, du - * fait d'un changement de système : - * - Utiliser des noms explicites dans le fichier de configuration (mais peut-être - * pas les textes qui s'affichent dans la page de configuration, car susceptibles - * d'être changés) ; les identifiants d'items de menus ne devraient pas être - * accessibles aux utilisateurs, ils peuvent aussi changer inopinément, et ils vont - * certainement le faire. Penser plutôt à des noms mnémoniques, un peu comme ceux - * qu'on trouve dans le fichier "ressource.h", mais sans les préfixes "IDM_", avec - * un peu plus de minuscules et moins de "underscores". + * \todo Considérer les améliorations suivantes (notamment pour faire en sorte que les + * utilisateurs "avancés" qui voudraient éditer manuellement le fichier "config.ini" + * n'aient pas trop de mal à s'y retrouver) : * - Regrouper les items de cette nature sous un groupe parent spécifique * (donc pas sous "[Config]" ni "[Debug]"). - * - Ne sauvegarder que les raccourcis dont la valeur diffère de la valeur par défaut - * (éventuellement détruire explicitement ceux qui sont revenus à cette valeur par - * défaut après avoir été changés). * - Grouper la configuration principale et la configuration alternative dans le même * item (par exemple avec la syntaxe suivante : 0,0,0,0/0,0,0,0) **/ @@ -297,7 +300,7 @@ * \param[in] prefixe2 nom de la chaîne enregistrée * \param[in] extension extension du fichier (permet de définir le type du fichier (BMP, MPG, TS, ...) **/ - NomFichierAvecDate(LPCTSTR dir, LPCSTR prefixe1, LPCSTR prefixe2, LPCTSTR extension); + NomFichierAvecDate(LPCTSTR dir, LPCTSTR prefixe1, LPCSTR prefixe2, LPCTSTR extension); /** * Ouvre le fichier (d'enregistrement) en écriture * Modifié: trunk/internet.cpp =================================================================== --- trunk/internet.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/internet.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -81,7 +81,7 @@ * \param[in] useragent User-Agent devant être utilisé **/ void ConnexionInternet::SetUserAgent(LPCTSTR useragent) { - UINT longueur = _tcslen(useragent); + UINT longueur = strlen_T(useragent); // Efface l'ancien (si spécifié if (this->m_user_agent) @@ -99,7 +99,7 @@ **/ void ConnexionInternet::SetUrl(LPCTSTR url) { // Nombre de caractères dans l'url passée - UINT longueur = _tcslen(url); + UINT longueur = strlen_T(url); // Libère l'ancienne url si alloué if (this->m_url) @@ -116,13 +116,14 @@ * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) * \retval 0 en cas d'erreur * \return une valeur de HTTP_ERR indiquant le status de la requète + * \todo Vérifier s'il n'y a pas de fuite de mémoire sur \p entete **/ int ConnexionInternet::EnvoieRequete(DWORD debut) { LPTSTR entete = 0; if (! this->m_hConnection) - // Pas de connexion, on l'établie donc - this->EtablieConnexion(); + // Pas de connexion, on l'établit donc + this->EtablitConnexion(); if (!this->m_hConnection) return 0; @@ -153,8 +154,8 @@ TCHAR taille[15]; _itot_s(debut, taille, _countof(taille), 10); // Récupération partielle - DWORD longueur = 15 /* Zone fixe de l'en tête*/ + _tcslen(taille); - entete = (LPTSTR)malloc(sizeof(TCHAR)*longueur); + UINT longueur = 15 /* Zone fixe de l'en tête*/ + strlen_T(taille); + entete = (LPTSTR)malloc(sizeof(TCHAR)*longueur); // Ceci est-il libéré quelque part ?? _tcscpy_s(entete, longueur, TEXT("Range: bytes=")); _tcscat_s(entete, longueur, taille); @@ -215,7 +216,7 @@ * \retval 0 une erreur est survenue * \retval 1 tout s'est bien passé **/ -int ConnexionInternet::EtablieConnexion() { +int ConnexionInternet::EtablitConnexion() { // Initialise la connexion this->m_hConnection = InternetOpen( this->m_user_agent, // User-agent @@ -311,7 +312,7 @@ NULL); // Inutilisé } // Fin de la récupération de l'en-tête - UINT size = _tcslen(this->m_content_type)+1; + UINT size = strlen_T(this->m_content_type)+1; if (*longueur < size) { *longueur = size; Modifié: trunk/internet.h =================================================================== --- trunk/internet.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/internet.h 2009-01-10 16:58:21 UTC (rev 163) @@ -125,5 +125,5 @@ void SetMethodePost() {_tcscpy_s(this->m_methode, 5, TEXT("POST"));}; /// Etablie la connexion - int EtablieConnexion(); + int EtablitConnexion(); }; \ Pas de fin de ligne à la fin du fichier Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/main.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -61,14 +61,14 @@ HICON hRecIcon = NULL; //!< Icône utilisée en mode enregistrement static HWND hSignalDlg = NULL; //!< Handle de la fenêtre de qualité du signal -wchar_t filtreMPEG2[256]; -wchar_t filtreAudio[256]; -wchar_t filtreAc3[256]; +TCHAR filtreMPEG2[256]; +TCHAR filtreAudio[256]; +TCHAR filtreAc3[256]; TCHAR nomVille[256]; bool exact_match; -wchar_t nom_tuner[256]; -wchar_t nom_receiver[256]; +TCHAR nom_tuner[256]; +TCHAR nom_receiver[256]; int avance_enreg; int retard_enreg; int offset_tuner; @@ -83,8 +83,10 @@ /// Délai d'attente avant basculement des bordures #define DUREE_SWITCH_BORDER 400 + /// Délai de persistance du curseur (pointeur souris) en mode plein écran : #define DUREE_CURSEUR 3000 // Valeur en millisecondes + /// Délai d'attente avant affichage des informations OSD de la chaîne, une fois qu'on /// a changé de chaîne #define DUREE_SHOW_PROGRAMME 2000 @@ -820,9 +822,10 @@ RedrawWindow(hMainWnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE); if (hMainStatus != NULL) { - CHAR str[40]; + TCHAR str[40]; - SendMessageA(hMainStatus, SB_SETTEXTA, 0, (LPARAM)canal_courant.nom); + strcpy_T(str, canal_courant.nom); + SendMessage(hMainStatus, SB_SETTEXT, 0, (LPARAM)str); for (int nEmis=0; nEmis<=1; nEmis++) { const Emission & emis = canal_courant.emis[nEmis]; @@ -830,13 +833,13 @@ str[0] = 0; if (emis.cle) TimeToStr(emis.debut, str, _countof(str)); - SendMessageA(hMainStatus, SB_SETTEXTA, nEmis*2+1, (LPARAM)str); - SendMessageA(hMainStatus, SB_SETTEXTA, nEmis*2+2, (LPARAM)(emis.cle ? emis.nom : "")); + SendMessage(hMainStatus, SB_SETTEXT, nEmis*2+1, (LPARAM)str); + SendMessage(hMainStatus, SB_SETTEXT, nEmis*2+2, (LPARAM)(emis.cle ? emis.nom : TEXT(""))); } if (!use_osd) { - sprintf_s(str, "%s %i", muted ? "Volume" : "Sourdine", (volumeCourant+8000)/80); - SendMessageA(hMainStatus, SB_SETTEXTA, 5, (LPARAM)str); + _stprintf_s(str, TEXT("%s %i"), muted ? TEXT("Volume") : TEXT("Sourdine"), (volumeCourant+8000)/80); + SendMessage(hMainStatus, SB_SETTEXT, 5, (LPARAM)str); } } @@ -942,10 +945,10 @@ { // Ajoute les différents contributeurs RcdataResource resource; - if ( ExtraitRcdataResource(MAKEINTRESOURCE(IDR_AUTHORS), &resource) ) { + + if (resource.Extraction(IDR_AUTHORS)) { // Tout s'est bien passé: on peut utiliser la liste des contributeurs - SetDlgItemTextA(hwndDlg, IDC_AUTHORS, (LPCSTR)resource.contenu); - delete [] resource.contenu; + SetDlgItemTextA(hwndDlg, IDC_AUTHORS, resource); } // Ajoute la version dans la fenêtre @@ -2300,7 +2303,8 @@ break; default: - myprintf(TEXT("Erreur option %d : (%s:%d)"), j, __FILE__, __LINE__); + myprintf(TEXT("Erreur option %d : (%s:%d)"), + j, TEXT(__FILE__), __LINE__); break; } break; @@ -2318,7 +2322,7 @@ { // Première chose à faire: - // Vérifier si une autre version ne fonctionne pas déjà + // Vérifier si une autre instance ne fonctionne pas déjà HANDLE hMutex = CreateMutex(NULL, TRUE, szAppName); bool bQuitte = true, // Indique qu'il faut quitter @@ -2339,9 +2343,10 @@ // // Regarde si un fichier dont le nom se finit par «_» existe dans le dossier actuel de PTVM WIN32_FIND_DATA fd = {0}; // Pour rechercher les fichiers - TCHAR chemin[MAX_PATH]; // Dossier actuel + patern pour la recherche de fichiers de mise à jour - _tcscpy_s(chemin, _countof(chemin), pouchindir_prog); - _tcscat_s(chemin, _countof(chemin), TEXT("*_")); + TCHAR chemin[MAX_PATH]; // Dossier actuel + pattern pour la recherche de fichiers de mise à jour + + strcpy_T(chemin, pouchindir_prog); + strcat_T(chemin, TEXT("*_")); // On recherche HANDLE hSearch = FindFirstFile(chemin, &fd); @@ -2404,8 +2409,20 @@ #endif // #if USE_CONSOLE==1 #if USE_CONSOLE // Affiche divers renseignements pour le debogguage - myprintf(TEXT("Compile le : %S %S\n"), __DATE__, __TIME__); - myprintf(TEXT("Version : %") A2t TEXT("\n"), PTVM_VERSION_STR); + myprintf(TEXT("Compile le : %") A2t TEXT(" %") A2t TEXT("\n"), __DATE__, __TIME__); + myprintf(TEXT("Version : ") TEXT(PTVM_VERSION_STR) TEXT(" (") + #ifdef _UNICODE + TEXT("Unicode") + #else + TEXT("SBCS") + #endif + TEXT("), ") +#ifdef _WIN64 + TEXT("x64") +#else + TEXT("Win32") +#endif + TEXT("\n")); myprintf(TEXT("Tuner : %s\nRécepteur : %s\nMPEG2 : %s\nAudio : %s\nAC3 : %s\nVille : %s\n"), nom_tuner, @@ -2414,7 +2431,7 @@ filtreAudio, filtreAc3, nomVille); - myprintf(TEXT("Ligne de commande : \"%s\"\n"), GetCommandLine()); + myprintf(TEXT("Ligne de commande : [%s]\n"), GetCommandLine()); #endif // #if USE_CONSOLE // Vérifie l'existence du fichier "canaux.ini", et le crée à partir des ressources @@ -2423,8 +2440,8 @@ // Récupère la version de windows // et initialise la variable indiquant si on tourne sous Vista - ZeroMemory(&windows_version, sizeof(OSVERSIONINFOEX)); - windows_version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + ZeroMemory(&windows_version, sizeof(windows_version)); + windows_version.dwOSVersionInfoSize = sizeof(windows_version); if (GetVersionEx((OSVERSIONINFO *)&windows_version)) { if (windows_version.dwMajorVersion >= 6) { is_vista = true; @@ -2433,21 +2450,14 @@ if (vmr_mode==vmt_VMR7_renderless) use_osd = false; - myprintf(L"Fonctionne sous Vista ou 2008 Serveur ou plus récent\t"); + myprintf(TEXT("Fonctionne sous Vista ou 2008 Serveur ou plus récent\t")); } else { myprintf(TEXT("Fonctionne sous 2000 ou XP\t")); } } else { myprintf(TEXT("Erreur lors de la récupération de la version de Windows\t")); } - myprintf( -#ifdef _WIN64 - TEXT("x64") -#else - TEXT("Win32") -#endif - TEXT("\n##########\n\n") - ); + myprintf(TEXT("\n##########\n\n")); HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); if (FAILED(hr)) { Modifié: trunk/main.h =================================================================== --- trunk/main.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/main.h 2009-01-10 16:58:21 UTC (rev 163) @@ -29,8 +29,7 @@ #include "base.h" -// Nom de l'application -extern TCHAR szAppName[]; +extern TCHAR szAppName[]; //!< Nom de l'application (pour le titre de la fenêtre) extern WORD sidChaineConfig; //!< SID chaîne récupéré dans 'config.ini' @@ -50,19 +49,16 @@ * @{ **/ -extern wchar_t filtreMPEG2[256]; //!< Nom du codec Audio MPEG2 choisi -#ifdef TEST_H264 -extern wchar_t filtreH264[256]; //!< Nom du codec H264, utilisé pour la HD -#endif -extern wchar_t filtreAudio[256]; //!< Nom du codec Audio MPEG2 choisi -extern wchar_t filtreAc3[256]; //!< Nom du codec AC3 choisi +extern TCHAR filtreMPEG2[256]; //!< Nom du codec Audio MPEG2 choisi +extern TCHAR filtreAudio[256]; //!< Nom du codec Audio MPEG2 choisi +extern TCHAR filtreAc3[256]; //!< Nom du codec AC3 choisi extern TCHAR nomVille[256]; //!< Nom de la ville de l'utilisateur extern bool exact_match; //!< Indique si une correspondance exacte est souhaitée //!< dans la recherche de filtres -extern wchar_t nom_tuner[256]; //!< Nom du tuner à utiliser -extern wchar_t nom_receiver[256]; //!< Nom du récepteur à utiliser +extern TCHAR nom_tuner[256]; //!< Nom du tuner à utiliser +extern TCHAR nom_receiver[256]; //!< Nom du récepteur à utiliser extern TCHAR screenshots_dir[MAX_PATH]; //!< Répertoire pour les captures d'écran extern TCHAR video_dir[MAX_PATH]; //!< Répertoire pour les enregistrements vidéo @@ -158,18 +154,3 @@ * Met à jour les raccourcis dans les menus **/ void update_shortcuts_menus(); - -/** - * Extrait une resource de type RCData du fichier - * - * Paramètres: - * LPCWSTR nom_resource: nom de la resource. Utiliser MAKEINTRESOURCE pour des entiers. - * RcdataResource: chaîne contenant le retour. Initialisé par la fonction. - * La taille du tableau aussi; - * Ne pas oublier de faire un delete une fois utilisé... - * - * Retour: - * 1 en cas de succes - * 0 en cas d'échec - **/ -int ExtraitRcdataResource(LPCWSTR nom_resource, RcdataResource *resource); Modifié: trunk/mpeg2defs.cpp =================================================================== --- trunk/mpeg2defs.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/mpeg2defs.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -38,14 +38,19 @@ #include #include "mpeg2defs.h" -/* - * Récupération d'une chaîne de caractères à partir d'un pointeur sur début et d'une longueur. - * La chaîne source n'est PAS (nécessairement) terminée par zéro. - * Version pour adresse de destination type LPSTR (caractères 8 bits) : +/** + * Copie d'une chaîne de caractères avec encodage optionnel, à partir d'un pointeur sur début + * et d'une longueur. La chaîne source n'est PAS (nécessairement) terminée par zéro. + * Version pour adresse de destination type \p CHAR (caractères 8 bits) : * Si un caractère d'encodage est présent au début de la chaîne (code 0x01 à 0x1f), celui-ci * est éliminé, et il est retourné par la fonction (qui autrement retourne 0). * Aucune conversion n'est cependant effectuée en relation avec ce code. - */ + * \param[in] src Pointeur sur la chaîne source + * \param[in] siz Longueur de la chaîne source + * \param[out] dst Pointeur sur un tampon destiné à recevoir la chaîne de destination + * \param[in] bufsize Longueur du tampon destiné à recevoir la chaîne de destination + * \retval Code de page qui était présent au début de la chaîne source, ou bien 0 s'il n'y en avait pas. + **/ UINT get_raw_str(LPCSTR src, UINT siz, LPSTR dst, UINT bufsize) { UINT ixcp = 0; @@ -61,17 +66,22 @@ return ixcp; } -/* - * Récupération d'une chaîne de caractères à partir d'un pointeur sur début et d'une longueur. - * La chaîne source n'est PAS (nécessairement) terminée par zéro. - * Version pour adresse de destination type LPWSTR (caractères 16 bits) : - * Si un caractère d'encodage est présent au début de la chaîne (code 0x01 à 0x1f), celui-ci - * est éliminé, et il est retourné par la fonction (qui autrement retourne 0). - * De plus, dans ce dernier cas, il est tenté, dans la mesure du possible, d'utiliser ce code - * pour convertir la chaîne de caractères en chaîne Unicode. - * Les codes de contrôle éventuels (0x80 à 0x9f) sont convertis en codes de 0xe080 à 0xe09f. - * Si au moins un code de ce type est présent, la valeur 0x100 est ajoutée au code de retour. - */ +/** + * Copie d'une chaîne de caractères avec encodage optionnel, à partir d'un pointeur sur début + * et d'une longueur. La chaîne source n'est PAS (nécessairement) terminée par zéro. + * Version pour adresse de destination type \p WCHAR (caractères 16 bits) : + * - Si un caractère d'encodage est présent au début de la chaîne (code 0x01 à 0x1f), celui-ci + * est éliminé, et il est retourné par la fonction (qui autrement retourne 0). + * - De plus, dans ce dernier cas, il est tenté, dans la mesure du possible, d'utiliser ce code + * pour convertir la chaîne de caractères en chaîne Unicode. + * - Les codes de contrôle éventuels (0x80 à 0x9f) sont convertis en codes de 0xe080 à 0xe09f. + * \param[in] src Pointeur sur la chaîne source + * \param[in] siz Longueur de la chaîne source + * \param[out] dst Pointeur sur un tampon destiné à recevoir la chaîne de destination + * \param[in] bufsize Longueur du tampon destiné à recevoir la chaîne de destination + * \retval Code de page qui était présent au début de la chaîne source, ou bien 0 s'il n'y en avait pas. + * Si au moins un code de contrôle était présent dans la chaîne, alors la valeur 0x100 est ajoutée + **/ UINT get_raw_str(LPCSTR src, UINT siz, LPWSTR dst, UINT bufsize) { static const UINT16 codepages[0x20] = { Modifié: trunk/mpeg2defs.h =================================================================== --- trunk/mpeg2defs.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/mpeg2defs.h 2009-01-10 16:58:21 UTC (rev 163) @@ -511,25 +511,35 @@ }; /** - * Récupération d'une chaîne de caractères à partir d'un pointeur sur début et d'une longueur. - * La chaîne source n'est PAS (nécessairement) terminée par zéro. - * Version pour adresse de destination type LPSTR (caractères 8 bits) : + * Copie d'une chaîne de caractères avec encodage optionnel, à partir d'un pointeur sur début + * et d'une longueur. La chaîne source n'est PAS (nécessairement) terminée par zéro. + * Version pour adresse de destination type \p CHAR (caractères 8 bits) : * Si un caractère d'encodage est présent au début de la chaîne (code 0x01 à 0x1f), celui-ci * est éliminé, et il est retourné par la fonction (qui autrement retourne 0). * Aucune conversion n'est cependant effectuée en relation avec ce code. + * \param[in] src Pointeur sur la chaîne source + * \param[in] siz Longueur de la chaîne source + * \param[out] dst Pointeur sur un tampon destiné à recevoir la chaîne de destination + * \param[in] bufsize Longueur du tampon destiné à recevoir la chaîne de destination + * \retval Code de page qui était présent au début de la chaîne source, ou bien 0 s'il n'y en avait pas. **/ UINT get_raw_str(LPCSTR src, UINT siz, LPSTR dst, UINT bufsize); /** - * Récupération d'une chaîne de caractères à partir d'un pointeur sur début et d'une longueur. - * La chaîne source n'est PAS (nécessairement) terminée par zéro. - * Version pour adresse de destination type LPWSTR (caractères 16 bits) : + * Copie d'une chaîne de caractères avec encodage optionnel, à partir d'un pointeur sur début + * et d'une longueur. La chaîne source n'est PAS (nécessairement) terminée par zéro. + * Version pour adresse de destination type \p WCHAR (caractères 16 bits) : * - Si un caractère d'encodage est présent au début de la chaîne (code 0x01 à 0x1f), celui-ci * est éliminé, et il est retourné par la fonction (qui autrement retourne 0). * - De plus, dans ce dernier cas, il est tenté, dans la mesure du possible, d'utiliser ce code * pour convertir la chaîne de caractères en chaîne Unicode. * - Les codes de contrôle éventuels (0x80 à 0x9f) sont convertis en codes de 0xe080 à 0xe09f. - * - Si au moins un code de ce type est présent, la valeur 0x100 est ajoutée au code de retour. + * \param[in] src Pointeur sur la chaîne source + * \param[in] siz Longueur de la chaîne source + * \param[out] dst Pointeur sur un tampon destiné à recevoir la chaîne de destination + * \param[in] bufsize Longueur du tampon destiné à recevoir la chaîne de destination + * \retval Code de page qui était présent au début de la chaîne source, ou bien 0 s'il n'y en avait pas. + * Si au moins un code de contrôle était présent dans la chaîne, alors la valeur 0x100 est ajoutée **/ UINT get_raw_str(LPCSTR src, UINT siz, LPWSTR dst, UINT bufsize); Modifié: trunk/network.cpp =================================================================== --- trunk/network.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/network.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -38,7 +38,7 @@ HRESULT CPinBidon::CheckMediaType(const CMediaType *pmt) { -// myprintf(L"CheckMediaType\n"); +// myprintf(TEXT("CheckMediaType\n")); if (*pmt->Type() == KSDATAFORMAT_TYPE_BDA_ANTENNA) return S_OK; return S_FALSE; @@ -60,18 +60,18 @@ HRESULT CPinBidon::FillBuffer(IMediaSample *pSamp) { - //myprintf(L"CPinBidon FillBuffer\n"); + //myprintf(TEXT("CPinBidon FillBuffer\n")); return S_OK; } HRESULT CPinBidon::DecideBufferSize(IMemAllocator * pAlloc,ALLOCATOR_PROPERTIES * ppropInputRequest) { - //myprintf(L"CPinBidon DecideBufferSize\n"); + //myprintf(TEXT("CPinBidon DecideBufferSize\n")); return S_OK; } CNetworkProvider::CNetworkProvider(IUnknown *pUnk, HRESULT *phr) : - CSource(szFilterName, NULL, __uuidof(this)) + CSource(WCHAR2TCHAR(szFilterName), NULL, __uuidof(this)) { HRESULT hr; m_bidon = new CPinBidon(&hr, this); @@ -92,7 +92,7 @@ delete m_bidon; } -LPCTSTR CNetworkProvider::szFilterName = TEXT("Network Provider PTvM"); +LPCWSTR CNetworkProvider::szFilterName = L"Network Provider PTvM"; CUnknown * WINAPI CNetworkProvider::CreateInstance(IUnknown *pUnk, HRESULT *phr) // static { @@ -122,6 +122,6 @@ // Return a non-addref'd pointer to pin n // needed by CBaseFilter CBasePin *CNetworkProvider::GetPin(int n) { -// myprintf(L"GetPin %i\n", n); +// myprintf(TEXT("GetPin %i\n"), n); return (n==0) ? m_bidon : NULL; } Modifié: trunk/parse.cpp =================================================================== --- trunk/parse.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/parse.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -66,7 +66,7 @@ descrScanner sd(se().descrRange()); //if (debug) - // myprintf(L"type : %02X, pid : %i\n", stream_type, pid); + // myprintf(TEXT("type : %02X, pid : %i\n"), stream_type, pid); switch (stream_type) { case st_MPEG_1_video: //ISO_IEC_11172_2_VIDEO, MPEG-1 video streams @@ -106,7 +106,7 @@ UINT8 length = sd().length; //if (debug) - // myprintf(L"sous_type : %02X, sous_taille : %i\n", tag, length); + // myprintf(TEXT("sous_type : %02X, sous_taille : %i\n"), tag, length); if (tag == mdt_ISO_639_Language && length > 0) { une_piste & pmt_son = lpmt_e.sons.tbl[lpmt_e.sons.nbr-1]; @@ -146,7 +146,8 @@ canal.TSID = tsid; canal.SID = se().service_id(); - myprintf(TEXT("Groupe : %") A2t TEXT(", Chaine : %") A2t TEXT(", SID : %i\n"), canal.groupe, canal.nom, se().service_id()); + myprintf(TEXT("Groupe : %") A2t TEXT(", Chaine : %") A2t TEXT(", SID : %i\n"), + canal.groupe, canal.nom, se().service_id()); Canaux.push_back(canal); break; @@ -160,10 +161,10 @@ #if USE_CONSOLE for (descrScanner sd(nit.descrRange()); !sd; ++sd) { if (sd().tag() == mdt_Network_Name) { - char nom[256]; + TCHAR nom[256]; // sd().as().get_network_name(nom); - myprintf(TEXT("parse_nit: Nom réseau : %") A2t TEXT("\n"), nom); + myprintf(TEXT("parse_nit: Nom réseau : %s\n"), nom); } } #endif // #if USE_CONSOLE @@ -174,16 +175,16 @@ chIDs.TSID = se().tsid(); chIDs.ONID = se().onid(); - // myprintf(L"parse_nit: TSID=%i, ONID=%i, taille=%i\n", chIDs.TSID, chIDs.ONID, se().dloop_length()); + // myprintf(TEXT("parse_nit: TSID=%i, ONID=%i, taille=%i\n"), chIDs.TSID, chIDs.ONID, se().dloop_length()); for (descrScanner sed(se().descrRange()); !sed; ++sed) { - // myprintf(L"parse_nit: type : %02X, taille : %i\n", sed().tag(), sed().length); + // myprintf(TEXT("parse_nit: type : %02X, taille : %i\n"), sed().tag(), sed().length); if (sed().tag() == mdt_Logical_Channel) { for (streamScanner seds(sed().as().subDescrRange()); !seds; ++seds) { chIDs.SID = seds().service_id(); chIDs.numero_nit = seds().logical_channel_number(); - //myprintf(L"parse_nit: ONID=%i, TSID=%i, SID=%i, numero=%i\n", + //myprintf(TEXT("parse_nit: ONID=%i, TSID=%i, SID=%i, numero=%i\n"), // chIDs.ONID, chIDs.TSID, chIDs.SID, chIDs.numero_nit); chaineIDs.push_back(chIDs); } @@ -268,8 +269,8 @@ // le reste du traitement de la fonction est annulé. Mpeg2SectionsHandler handler; - size_t prev_size = Canaux.size(); // Mémoriser le nombre de chaînes déjà identifiées à cet instant - unsigned i; + UINT prev_size = (UINT)Canaux.size(); // Mémoriser le nombre de chaînes déjà identifiées à cet instant + UINT i; myprintf(TEXT("######################################\nscan de la fréquence : %i\n"), freq.khz); Modifié: trunk/pmtfilter.cpp =================================================================== --- trunk/pmtfilter.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/pmtfilter.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -37,17 +37,17 @@ #include "crc32.h" CPMTFilter::CPMTFilter(IUnknown *pUnk, HRESULT *phr) : - CBaseRenderer(__uuidof(this), szFilterName, pUnk, phr) + CBaseRenderer(__uuidof(this), WCHAR2TCHAR(szFilterName), pUnk, phr) { - myprintf(TEXT("%s construit\n"), szFilterName); + myprintf(TEXT("%") W2t TEXT(" construit\n"), szFilterName); } CPMTFilter::~CPMTFilter() { - myprintf(TEXT("%s detruit\n"), szFilterName); + myprintf(TEXT("%") W2t TEXT(" detruit\n"), szFilterName); } -LPCTSTR CPMTFilter::szFilterName = TEXT("Filtre PMT PTvM"); +LPCWSTR CPMTFilter::szFilterName = L"Filtre PMT PTvM"; CUnknown * WINAPI CPMTFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr) // static { @@ -68,7 +68,7 @@ const SI_PMT * ppmt; size_t taille = pMediaSample->GetActualDataLength(); -// myprintf(L"PMT DoRenderSample %i\n", taille); +// myprintf(TEXT("PMT DoRenderSample %i\n"), taille); pMediaSample->GetPointer((LPBYTE *)(&ppmt)); if ( Modifié: trunk/pmtfilter.h =================================================================== --- trunk/pmtfilter.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/pmtfilter.h 2009-01-10 16:58:21 UTC (rev 163) @@ -40,6 +40,6 @@ HRESULT DoRenderSample(IMediaSample *pMediaSample); HRESULT CheckMediaType(const CMediaType *pmt); - static LPCTSTR szFilterName; - static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr); + static LPCWSTR szFilterName; // Ne PAS convertir en LPCTSTR (TCHAR) + static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr); }; Modifié: trunk/record.cpp =================================================================== --- trunk/record.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/record.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -68,7 +68,7 @@ fin = pProg->fin; apres = pProg->apres; pProg->etat = epr_encours; // état de la nouvelle programmation utilisée - strcpy_s(nom, _countof(nom), pProg->nom); + strcpy_T(nom, pProg->nom); } } return true; @@ -209,7 +209,7 @@ * Obtenir le pointeur sur le nom d'une programmation si celle-ci a été explicitement * nommée, et NULL dans le cas contraire : **/ -static LPSTR getProgName(Programme * pProg) +static LPTSTR getProgName(Programme * pProg) { if (pProg!=NULL && !pProg->nomAuto && *pProg->nom!=0) return pProg->nom; Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/recprog.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -250,7 +250,7 @@ const Programme & prog_verif = Programmes[i]; if (!modif) { - if (strcmp(prog_verif.nom, nom) == 0) { + if (_tcscmp(prog_verif.nom, nom) == 0) { affiche_erreurs(TEXT("Ce nom est déjà utilisé")); return false; } @@ -262,7 +262,7 @@ // Vérifier qu'on n'a pas programmé plusieurs fois la même chaîne au même moment : if (!modif && sidChaine==prog_verif.sidChaine && isMultiplex()==prog_verif.isMultiplex()) { _stprintf_s(buffer, _countof(buffer), - TEXT("Chevauchement des horaires avec \"%") A2t TEXT("\", qui concerne la même chaîne !"), + TEXT("Chevauchement des horaires avec \"%s\", qui concerne la même chaîne !"), prog_verif.nom); affiche_erreurs(buffer); return false; @@ -271,7 +271,7 @@ // Vérifie que le programme chevauchant est sur le même multiplex : if (getFrequence_par_sid(prog_verif.sidChaine) != canal.khz) { _stprintf_s(buffer, _countof(buffer), - TEXT("Chevauchement des horaires avec \"%") A2t TEXT("\" sur %") A2t TEXT(", qui ne partage pas le même multiplex !"), + TEXT("Chevauchement des horaires avec \"%s\" sur %") A2t TEXT(", qui ne partage pas le même multiplex !"), prog_verif.nom, canal.nom); affiche_erreurs(buffer); return false; @@ -490,13 +490,13 @@ * Trouver l'index de l'enregistrement programmé dont le nom est 'nom'. * Retourne -1 si nom vide ou rien trouvé. **/ -int trouve_prog_par_nom(LPCSTR nom) +int trouve_prog_par_nom(LPCTSTR nom) { if (nom && nom[0] != 0) { int nbProgrammes = (int)Programmes.size(); for (int i=0; i0 && *pwrk<=' ') // attention, type CHAR signé !! pwrk++; if (pwrk>pnom) - strcpy_s(pnom, bufSize, pwrk); + strcpy_T(pnom, bufSize, pwrk); // Supprimer les espaces de fin : - size_t strSize = strlen(pnom); - while (strSize>0 && pnom[strSize-1]<=' ') + UINT strSize = strlen_T(pnom); + while (strSize>0 && pnom[strSize-1]>0 && pnom[strSize-1]<=' ') pnom[--strSize] = 0; } @@ -841,15 +841,16 @@ // do { ixSuffNom++; - sprintf_s(nom, _countof(nom), ixSuffNom>1 ? "%s-%i-%02i_%u" : "%s-%i-%02i", + _stprintf_s(nom, _countof(nom), + ixSuffNom>1 ? TEXT("%") A2t TEXT("-%i-%02i_%u") : TEXT("%") A2t TEXT("-%i-%02i"), prog.isMultiplex() ? "Multiplex" : canal.nom, prog.debut.wDay, prog.debut.wMonth, ixSuffNom); - } while (strcmp(nom, prog.nom)!=0 && trouve_prog_par_nom(nom)>=0); - strcpy_s(prog.nom, _countof(prog.nom), nom); + } while (_tcscmp(nom, prog.nom)!=0 && trouve_prog_par_nom(nom)>=0); + strcpy_T(prog.nom, nom); prog.nomAuto = true; } } else { - strcpy_s(prog.nom, _countof(prog.nom), nom); + strcpy_T(prog.nom, nom); prog.nomAuto = false; } @@ -880,7 +881,7 @@ // (en fait, uniquement les items susceptibles d'être contenus dans le guide EPG) CtlSelChannel(GetDlgItem(hDlg, IDC_CHANNEL), trouve_chaine_par_sid(prog.sidChaine)); - SendDlgItemMessageA(hDlg, IDC_NAME, WM_SETTEXT, 0, LPARAM(prog.nomAuto ? "" : prog.nom)); + SendDlgItemMessage(hDlg, IDC_NAME, WM_SETTEXT, 0, LPARAM(prog.nomAuto ? TEXT("") : prog.nom)); SetCtlTimeDate(hDlg, IDC_DATE_START, IDC_TIME_START, dtc_debut = prog.debut); SetCtlTimeDate(hDlg, IDC_DATE_END, IDC_TIME_END, dtc_fin = prog.fin); @@ -902,7 +903,7 @@ const Emission & emis = canal.emis[noEmis]; - strcpy_s(prog.nom, _countof(prog.nom), emis.nom); + strcpy_T(prog.nom, emis.nom); prog.sidChaine = canal.SID; prog.numeroChaine = canal.numeroChaine; prog.apres = apr_rien; @@ -1014,9 +1015,9 @@ { static HWND hListItem = NULL; int i; - static int selection = -1; // Index de l'item couramment sélectionné si >= 0 - static NomProg selProgNom = ""; // Nom de la sélection courante (pour pouvoir reconstituer celle-ci - // après modification ou tri de la liste) + static int selection = -1; // Index de l'item couramment sélectionné si >= 0 + static NomProg selProgNom = TEXT(""); // Nom de la sélection courante (pour pouvoir reconstituer celle-ci + // après modification ou tri de la liste) switch (uMsg) { @@ -1090,7 +1091,7 @@ // Coche les cases pour les répétitions : SetCtlRepeat(hDlg, IDC_REP_BASE, prog.repetition); - strcpy_s(selProgNom, _countof(selProgNom), prog.nom); + strcpy_T(selProgNom, prog.nom); return TRUE; } update_edit_state(hDlg, selection); @@ -1167,7 +1168,7 @@ prog = newprog; - strcpy_s(selProgNom, _countof(selProgNom), prog.nom); + strcpy_T(selProgNom, prog.nom); prog.ajoutTacheAvecLogon(hDlg); finalize_prog_change(); @@ -1183,7 +1184,7 @@ if (!dlgToProg(hDlg, prog, false)) return FALSE; - strcpy_s(selProgNom, _countof(selProgNom), prog.nom); + strcpy_T(selProgNom, prog.nom); prog.ajoutTacheAvecLogon(hDlg); Programmes.push_back(prog); @@ -1835,7 +1836,7 @@ **/ bool do_record_events() { - // myprintf(L"Appel do_record_events()\n"); + // myprintf(TEXT("Appel do_record_events()\n")); SYSTEMTIME localtime; Modifié: trunk/recprog.h =================================================================== --- trunk/recprog.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/recprog.h 2009-01-10 16:58:21 UTC (rev 163) @@ -67,7 +67,7 @@ epr_null = -1 // pseudo-valeur pour dire "ne pas modifier" }; -typedef char NomProg[64]; // Type pour nom donné à une programmation +typedef TCHAR NomProg[64]; // Type pour nom donné à une programmation // Structure commune aux programmations d'enregistrement et aux enregistrements en cours : class RecordInfo @@ -151,7 +151,9 @@ /** * Traitement du chargement de la liste des programmes au démarrage, et purge - * des enregistrements périmés : + * des enregistrements périmés + * \todo S'assurer que sont purgés aussi (par changement de date) les enregistrements + * avec répétitions, lorsque l'une de ces répétitions n'a pas pu être traitée. **/ void init_programmation(); @@ -207,7 +209,7 @@ * Trouver l'index de l'enregistrement programmé dont le nom est 'nom'. * Retourne -1 si nom vide ou rien trouvé. **/ -int trouve_prog_par_nom(LPCSTR nom); +int trouve_prog_par_nom(LPCTSTR nom); /** * Remplissage d'une combo-box de méthodes d'enregistement Modifié: trunk/rendering.cpp =================================================================== --- trunk/rendering.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/rendering.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -376,7 +376,7 @@ { cTopRight.SetText(TEXT("%") A2t, canal.nom); if (canal.emi_count > 0) - cTopRight2.SetText(TEXT("%") A2t, canal.emis[0].nom); + cTopRight2.SetText(TEXT("%s"), canal.emis[0].nom); } /// Effacement de tous les objets OSD affichés @@ -485,7 +485,7 @@ /// Ouverture du dialogue de propriétés du VMR VOID CVideoMixingRenderer::create_property_dialog() { - ::create_property_dialog(*this, L"VMR"); + ::create_property_dialog(*this, TEXT("VMR")); } /// Initialisation générale @@ -561,7 +561,7 @@ ar.x = vih->dwPictAspectRatioX; ar.y = vih->dwPictAspectRatioY; - //myprintf(L"Aspect ratio: x=%i, y=%i\n", ar.x, ar.y); + //myprintf(TEXT("Aspect ratio: x=%i, y=%i\n"), ar.x, ar.y); FreeMediaType(am); } @@ -789,7 +789,7 @@ { return create_and_add_filter( - CLSID_VideoMixingRenderer, L"Video Mixing Renderer", *this); + CLSID_VideoMixingRenderer, TEXT("Video Mixing Renderer"), *this); } HRESULT CVideoMixingRenderer7::Configure() @@ -964,7 +964,7 @@ { return create_and_add_filter( - CLSID_VideoMixingRenderer9, L"Video Mixing Renderer", *this); + CLSID_VideoMixingRenderer9, TEXT("Video Mixing Renderer"), *this); } HRESULT CVideoMixingRenderer9::Configure() Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/res.rc 2009-01-10 16:58:21 UTC (rev 163) @@ -400,7 +400,7 @@ IDD_UPDATE DIALOGEX 0, 0, 251, 155 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Vérification des mises à jours" +CAPTION "Vérification des mises à jour" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN PUSHBUTTON "&Vérifier",IDC_UPDATE_CHECK,57,112,50,14 Modifié: trunk/resource.h =================================================================== --- trunk/resource.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/resource.h 2009-01-10 16:58:21 UTC (rev 163) @@ -2,6 +2,7 @@ // Microsoft Visual C++ generated include file. // Used by res.rc // + #define IDI_PROG_ICON 101 #define IDI_ICON_REC 102 #define IDB_BITMAP 105 @@ -91,7 +92,8 @@ #define IDC_RETARD_ENREG 1072 #define IDC_RETARD_ENREG_UPDOWN 1073 #define IDC_REPETITIONS 1099 -#define IDC_REP_BASE 1100 + +#define IDC_REP_BASE 1100 // Offset de base pour les sept suivants #define IDC_REP_DIMANCHE 1100 #define IDC_REP_LUNDI 1101 #define IDC_REP_MARDI 1102 @@ -99,6 +101,7 @@ #define IDC_REP_JEUDI 1104 #define IDC_REP_VENDREDI 1105 #define IDC_REP_SAMEDI 1106 + #define IDC_SCAN 1107 #define IDC_RENUMBER 1108 #define IDC_RENUM_SEQ 1109 @@ -115,9 +118,10 @@ #define IDC_UPDATE_CHECK 1120 #define IDC_UPDATE_LIST 1121 #define MY_TRAY_ICON_ID 20001 -#define IDM_CHAINES_BASE 39000 -#define IDM_PISTES_BASE 39500 -#define IDM_STOP_RECORD_BASE 39900 + +#define IDM_CHAINES_BASE 39000 // Offset de base pour changement chaîne +#define IDM_PISTES_BASE 39500 // Offset de base pour choix bande sonore +#define IDM_STOP_RECORD_BASE 39900 // Offset de base pour arrêt enregistrement #define IDM_QUIT 40000 #define IDM_ABOUT 40001 #define IDM_CONFIG 40002 @@ -138,10 +142,12 @@ #define IDM_MINIMIZE 40021 #define IDM_RESTORE 40022 #define IDM_ALWAYS_ON_TOP 40029 -#define IDM_CHAN_STATE_BASE 40030 + +#define IDM_CHAN_STATE_BASE 40030 // Offset de base pour les trois suivants #define IDM_CHAN_INACTIVE 40030 #define IDM_CHAN_ACTIVE 40031 #define IDM_CHAN_PREFERRED 40032 + #define IDM_REALTIME_PRIORITY 40034 #define IDM_HIGH_PRIORITY 40035 #define IDM_ABOVE_NORMAL_PRIORITY 40036 @@ -156,6 +162,7 @@ #define IDM_RECORD_STREAM 40047 #define IDM_STOP_RECORD 40048 #define IDM_DELAYED_STOP 40049 + #define IDM_VOL_AUG 40050 #define IDM_VOL_DIM 40051 #define IDM_ZOOM 40053 @@ -172,11 +179,17 @@ #define IDM_ETIRER 40066 #define IDM_UPDATE 40067 #define IDM_SHOW_PROGRAMME 40068 + #define IDM_CHAN_NUMERO 40069 #define IDM_CHAN_NOM 40070 #define IDM_CHAN_RESTORNUM 40071 #define IDM_CHAN_RESTORNOM 40072 +#define IDM_GRAPH_STATE 40042 // debug +#define IDM_RUN_GRAPH 40052 // debug +#define IDM_STOP_GRAPH 40064 // debug +#define IDM_TUNE_AGAIN 40065 // debug + // Next default values for new objects // #ifdef APSTUDIO_INVOKED Modifié: trunk/search.cpp =================================================================== --- trunk/search.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/search.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -33,10 +33,10 @@ // constaté avec certains tuners): struct VarStr_helper { - WCHAR str[128]; + TCHAR str[128]; VarStr_helper(const VARIANT & var); - LPCWSTR operator () () const {return str;} + LPCTSTR operator () () const {return str;} }; // Constructeur : @@ -46,7 +46,7 @@ strcpy_T(str, var.bstrVal); str[_countof(str)-1] = 0; // précaution - size_t len = wcslen(str); + size_t len = strlen_T(str); while (len>0 && str[--len]<=' ') str[len] = 0; Modifié: trunk/search.h =================================================================== --- trunk/search.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/search.h 2009-01-10 16:58:21 UTC (rev 163) @@ -63,7 +63,7 @@ * \retval S_FALSE si l'énumération doit s'arrêter (par exemple parce qu'on * a trouvé ce qu'on cherchait) */ - virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCWSTR pszName) = 0; + virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCTSTR pszName) = 0; /** * Application de la méthode virtuelle \p ApplyOne à chaque filtre trouvé. @@ -100,7 +100,7 @@ * \param[in] pszName nom du filtre * \return \p S_OK car tous les filtres doivent être énumérés */ - virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCWSTR pszName) + virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCTSTR pszName) { SendMessage(hItem, CB_ADDSTRING, 0, (LPARAM)pszName); return S_OK; @@ -113,7 +113,7 @@ */ class CSearchByType_Get : public CSearchByType { - LPCWSTR pszSearch; + LPCTSTR pszSearch; CComPtr & pFilter; public: /** @@ -125,14 +125,14 @@ * \param[in] pszSrch Nom du codec recherché. * \param[out] pFltr Pointeur ATL destiné recevoir l'interface du filtre trouvé, s'il existe. */ - CSearchByType_Get(GUID type, GUID subtype, bool bExactMatch, LPCWSTR pszSrch, CComPtr & pFltr) : + CSearchByType_Get(GUID type, GUID subtype, bool bExactMatch, LPCTSTR pszSrch, CComPtr & pFltr) : CSearchByType(type, subtype, bExactMatch), pszSearch(pszSrch), pFilter(pFltr) { myprintf( TEXT("CSearchByType_Get: type=") GUIDFMT TEXT("\n") - TEXT("\tsubtype=") GUIDFMT TEXT("\n\tnom=%") W2t TEXT("\n"), + TEXT("\tsubtype=") GUIDFMT TEXT("\n\tnom=%s\n"), GUIDPARM(type), GUIDPARM(subtype), pszSrch); pFltr.Release(); // précaution @@ -145,9 +145,9 @@ * \retval true tant que le codec n'a pas été trouvé * \retval false quand le codec a été trouvé, afin d'arrêter la recherche */ - virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCWSTR pszName) + virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCTSTR pszName) { - if (wcscmp(pszName, pszSearch)==0) { + if (_tcscmp(pszName, pszSearch)==0) { hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); return S_FALSE; } @@ -199,7 +199,7 @@ * \retval S_FALSE si l'énumération doit s'arrêter (par exemple parce qu'on * a trouvé ce qu'on cherchait) */ - virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCWSTR pszName) = 0; + virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCTSTR pszName) = 0; /** * Application de la méthode virtuelle \p ApplyOne à chaque filtre trouvé. @@ -233,7 +233,7 @@ * \param[in] pszName nom du filtre * \return \p S_OK car tous les filtres doivent être énumérés */ - virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCWSTR pszName) + virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCTSTR pszName) { if (filtre_compat(pCurFltr)!=compat_None) { myprintf(TEXT("CSearchByCategory_FillCombo : %s\n"), pszName); @@ -248,7 +248,7 @@ */ class CSearchByCategory_Get : public CSearchByCategory { - LPCWSTR pszSearch; + LPCTSTR pszSearch; CComPtr & pFilter; public: /** @@ -264,7 +264,7 @@ pFilter(pFltr) { myprintf( - TEXT("CSearchByCategory_Get: clsid=") GUIDFMT TEXT(", nom=%") W2t TEXT("\n"), + TEXT("CSearchByCategory_Get: clsid=") GUIDFMT TEXT(", nom=%s\n"), GUIDPARM(clsid), pszSrch); pFltr.Release(); // précaution @@ -277,9 +277,9 @@ * \retval true tant que le filtre n'a pas été trouvé * \retval false quand le filtre a été trouvé, afin d'arrêter la recherche */ - virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCWSTR pszName) + virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCTSTR pszName) { - if (wcscmp(pszName, pszSearch)==0) { + if (_tcscmp(pszName, pszSearch)==0) { pFilter = pCurFltr; return S_FALSE; } Modifié: trunk/settings.cpp =================================================================== --- trunk/settings.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/settings.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -340,11 +340,11 @@ ListView_SetItem(hListItem, &item); // Groute du multiplex de diffusion item.iSubItem = CHAN_COL_GROUP; - _stprintf_s(buffer, _countof(buffer), TEXT("%") A2t, canal.groupe); + strcpy_T(buffer, canal.groupe); ListView_SetItem(hListItem, &item); // Nom de la chaîne item.iSubItem = CHAN_COL_NAME; - _stprintf_s(buffer, _countof(buffer), TEXT("%") A2t, canal.nom); + strcpy_T(buffer, canal.nom); ListView_SetItem(hListItem, &item); // État de la chaîne (préféré, inactive, ...) State2LV(hListItem, iItem, canal.etat); @@ -780,7 +780,7 @@ **/ static void channel_number_changed(HWND hListItem, int iItem, LPCTSTR str_newnum) { - // Convertis le nouveau numéro en nombre + // Convertit le nouveau numéro en nombre WORD canal_no = (WORD)_tstoi(str_newnum); // Numéro valide ? @@ -1236,7 +1236,7 @@ // Changement de l'offset // On vérifie si la valeur entrée est valide LimitIntItemValue(hDlg, IDC_TUNER_OFFSET, -999, 999); - // ... (passage à travers) + // ... (passage à travers) // Changement dans un combo case _cmd_(IDC_COMBO_TUNER, LBN_SELCHANGE): @@ -1451,7 +1451,7 @@ int last_num = int(Canaux.size()); _stprintf_s(szFreq, _countof(szFreq), TEXT("%03u,%03u MHz"), freq.khz/1000, freq.khz%1000); - _stprintf_s(szTemp, _countof(szTemp), TEXT("Examen canal %u à %") W2t, freq.canal_no, szFreq); + _stprintf_s(szTemp, _countof(szTemp), TEXT("Examen canal %u à %s"), freq.canal_no, szFreq); SetWindowText(hInfoText, szTemp); tuning = true; pScan->tune(hDlg, freq, &stopping); @@ -1464,13 +1464,14 @@ const Chaine & canal = Canaux[last_num]; if (canal.nom[0]) { - char norme = canal.norme(); - char strnum[4] = "-"; // afficher '-' si zéro + CHAR norme = canal.norme(); + TCHAR strnum[4] = TEXT("-"); // afficher '-' si zéro if (canal.numeroChaine > 0) - _itoa_s(canal.numeroChaine, strnum, _countof(strnum), 10); -// swprintf_s(szTemp, _countof(szTemp), L"%S\t%u\t%s\t%S\t%S\t%c", strnum, canal.canal_no, szFreq, - _stprintf_s(szTemp, _countof(szTemp), TEXT("%") A2t TEXT("\t%u\t%") W2t TEXT("\t%") A2t TEXT("\t%") A2t TEXT("\t%c"), strnum, canal.canal_no, szFreq, + _itot_s(canal.numeroChaine, strnum, _countof(strnum), 10); + _stprintf_s(szTemp, _countof(szTemp), + TEXT("%s\t%u\t%s\t%") A2t TEXT("\t%") A2t TEXT("\t%c"), + strnum, canal.canal_no, szFreq, *canal.groupe ? canal.groupe : "", canal.nom, norme); AddLineToList(hListItem, szTemp); } @@ -1636,15 +1637,15 @@ static INT_PTR CALLBACK CaptureDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HWND hMotifNomsEnreg = NULL; - static HWND hVideoDirItem = NULL; - static HWND hSshotDirItem = NULL; + static HWND hVideoDirItem = NULL; + static HWND hSshotDirItem = NULL; switch (uMsg) { case WM_INITDIALOG: hMotifNomsEnreg = GetDlgItem(hDlg, IDC_MOTIF_NOM_REC); - hVideoDirItem = GetDlgItem(hDlg, IDC_MPEG2_DIR_VIEW); - hSshotDirItem = GetDlgItem(hDlg, IDC_SCREENSHOTS_DIR_VIEW); + hVideoDirItem = GetDlgItem(hDlg, IDC_MPEG2_DIR_VIEW); + hSshotDirItem = GetDlgItem(hDlg, IDC_SCREENSHOTS_DIR_VIEW); // Item de motif de nom d'enregistrements SendMessage(hMotifNomsEnreg, WM_SETTEXT, 0, (LPARAM)motif_noms_enreg); @@ -1868,7 +1869,7 @@ // Vide la liste ListView_DeleteAllItems(hList); // Ajoute les raccourcis - for (size_t i=0; i<_countof(shortcuts); i++) { + for (int i=0; i<_countof(shortcuts); i++) { const ShortcutItem &item = shortcuts[i]; if (item.nom[0] != 0) InsertShortcutItem(hList, i, item); @@ -2418,8 +2419,13 @@ if (pUnk) { CAUUID caGUID; - HRESULT hr = pPages->GetPages(&caGUID); + HRESULT hr = pPages->GetPages(&caGUID); +#ifdef _UNICODE + LPOLESTR pszTmp = LPOLESTR(nom); +#else + COPY_STR_ON_STACK(OLECHAR, pszTmp, nom, nLen); +#endif if (SUCCEEDED(hr)) { LCID lcid = GetUserDefaultLCID(); @@ -2429,7 +2435,7 @@ hMainWnd, 10, 10, - nom, + pszTmp, 1, &pUnk.p, caGUID.cElems, Modifié: trunk/trayicon.cpp =================================================================== --- trunk/trayicon.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/trayicon.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -46,7 +46,7 @@ if (hMainWnd != NULL) { hWnd = hMainWnd; uID = MY_TRAY_ICON_ID; - //myprintf(L"MyNOTIFYICONDATA::notify() - msg=%u, flg=0x%02x\n", dwMessage, uFlags); + //myprintf(TEXT("MyNOTIFYICONDATA::notify() - msg=%u, flg=0x%02x\n"), dwMessage, uFlags); return Shell_NotifyIcon(dwMessage, this)==TRUE; } return false; @@ -58,7 +58,7 @@ const Chaine & canal_courant = Canaux[ixChaineCourante]; _stprintf_s(szTip, _countof(szTip), - TEXT("%") A2t TEXT(" - %") A2t, canal_courant.nom, canal_courant.emis[0].nom); + TEXT("%") A2t TEXT(" - %s"), canal_courant.nom, canal_courant.emis[0].nom); uFlags |= NIF_TIP; } } Modifié: trunk/update.cpp =================================================================== --- trunk/update.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/update.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -111,7 +111,7 @@ * \retval true si tout s'est bien déroulé * \retval false en cas d'erreur **/ -bool SauveFichier(BYTE* contenu, size_t taille, LPCTSTR nom) { +static bool SauveFichier(BYTE* contenu, UINT taille, LPCTSTR nom) { bool ret = true; // prend le partie que tout est OK DWORD dwEcrit; // Nombre d'octets écrits @@ -138,7 +138,7 @@ * \retval true si tout s'est bien déroulé * \retval false en cas d'erreur **/ -bool RemplaceFichier(BYTE* contenu, size_t taille, LPCTSTR original, bool backup) { +static bool RemplaceFichier(BYTE* contenu, UINT taille, LPCTSTR original, bool backup) { bool ret = true; // prend le partie que tout est OK TCHAR fichierTemp[MAX_PATH]; // Fichier temporaire @@ -215,7 +215,7 @@ * \param[in] statut affiche la progression ? **/ DWORD GetInternetFile(LPCTSTR url, BYTE **data, eUPDATE_ACTION statut) { - // Si data est reseigné, on quitte + // Si data est renseigné, on quitte if (*data != NULL) return 0; @@ -260,7 +260,7 @@ *data = (LPBYTE)malloc(sizeof(BYTE)*(lu+1)); memcpy_s(*data, lu, temp, lu); } else { - // Déjà initialisé, on aggrandie le tableau + // Déjà initialisé, on aggrandit le tableau LPBYTE _temp = (LPBYTE)malloc(sizeof(BYTE)*dwLuTotal); memcpy_s(_temp, dwLuTotal, *data, dwLuTotal); free(*data); @@ -379,13 +379,13 @@ AddStatut(TEXT("Téléchargement de la mise à jour de Pouchin TV Mod..."), 0); - const char* url = xmlTypeMaj->FirstChild()->Value(); - int longueur = strlen(url)+1; - LPBYTE data = 0; - TCHAR *tUrl = (LPTSTR)malloc(sizeof(TCHAR)*longueur); - strcpy_T(tUrl, longueur, url); - size_t taille = GetInternetFile(tUrl, &data, eUpda_Telecharge); - free(tUrl); + LPCSTR url = xmlTypeMaj->FirstChild()->Value(); + + COPY_STR_ON_STACK(TCHAR, tUrl, url, longueur); + + LPBYTE data = 0; + size_t taille = GetInternetFile(tUrl, &data, eUpda_Telecharge); + if (taille) { // Des données ont été récupérées @@ -446,7 +446,7 @@ TCHAR fileName[MAX_PATH], pathName[MAX_PATH], *szIconeChar = 0; LPTSTR fichier = 0; // Regarde si on a des caractères UTF-8 dans la chaine, et les remplace le cas échéant - ConvertUTF82Char(szIconeUtf, &szIconeChar); + ConvertUTF82Char(szIconeUtf, szIconeChar); _tcscpy_s(fileName, _countof(fileName), szIconeChar); _tcscat_s(fileName, _countof(fileName), TEXT(".bmp")); _stprintf_s(pathName, _countof(pathName), TEXT("%s\\Icones"), pouchindir_prog); @@ -465,19 +465,19 @@ } else if (action == eUpda_Telecharge) { // Télécharge les images manquantes - const char *urlBase = xmlTypeMaj->Attribute("base"); - const char *urlPath = xmlIconesPack->Attribute("path"); - int longueur = strlen(urlBase) + strlen(urlPath) + strlen(szIconeUtf) + 6; // car path+"/"+icone+".bmp\0" - LPBYTE data = 0; - char *url = (char*)malloc(longueur); - TCHAR *tUrl = (TCHAR*)malloc(sizeof(TCHAR)*longueur); + LPCSTR urlBase = xmlTypeMaj->Attribute("base"); + LPCSTR urlPath = xmlIconesPack->Attribute("path"); + UINT longueur = strlen_T(urlBase) + strlen_T(urlPath) + strlen_T(szIconeUtf) + 6; // car path+"/"+icone+".bmp\0" + LPBYTE data = 0; + LPSTR url = (LPSTR)malloc(longueur); + LPTSTR tUrl = (LPTSTR)malloc(sizeof(TCHAR)*longueur); - // Obligé de passer la une convertion, car sinon, les caractères sont mal traduits + // Obligé de passer la une conversion, car sinon, les caractères sont mal traduits sprintf_s(url, longueur, "%s%s/%s.bmp", urlBase, urlPath, szIconeUtf); strcpy_T(tUrl, longueur, url); free(url); url=0; - // Envoie la connection - size_t taille = GetInternetFile(tUrl, &data, eUpda_Telecharge); + // Envoie la connexion + UINT taille = GetInternetFile(tUrl, &data, eUpda_Telecharge); free(tUrl); tUrl=0; if (taille) { // Des données ont été récupérées Modifié: trunk/utils.cpp =================================================================== --- trunk/utils.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/utils.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -71,6 +71,38 @@ } /** + * Version CHAR -> WCHAR (utilise \p MultiByteToWideChar). + * + * \param[in] pSrc Pointeur sur la chaîne source (CHAR) + * \param[in] nSizDst Taille du tampon de destination + * \param[out] pDst Pointeur sur le tampon de destination (WCHAR) + **/ +errno_t strcat_T(LPWSTR pDst, UINT nSizDst, LPCSTR pSrc) +{ + UINT nLen = strlen_T(pDst); + + if (nLen < nSizDst) + return strcpy_T(pDst+nLen, nSizDst-nLen, pSrc); + return EINVAL; +} + +/** + * Version WCHAR -> CHAR (utilise \p WideCharToMultiByte). + * + * \param[in] pSrc Pointeur sur la chaîne source (WCHAR) + * \param[in] nSizDst Taille du tampon de destination + * \param[out] pDst Pointeur sur le tampon de destination (CHAR) + **/ +errno_t strcat_T(LPSTR pDst, UINT nSizDst, LPCWSTR pSrc) +{ + UINT nLen = strlen_T(pDst); + + if (nLen < nSizDst) + return strcpy_T(pDst+nLen, nSizDst-nLen, pSrc); + return EINVAL; +} + +/** * Vérifie que les valeurs stockées sont dans la surface d'affichage actuelle * * \retval true si la zone est comprise dans l'affichage actuel @@ -180,9 +212,9 @@ * \param[out] str chaîne de caractères résultant * \param[in] str_size longeur max de la chaîne de caractères **/ -void TimeToStr(SYSTEMTIME st, char *str, size_t str_size) +void TimeToStr(SYSTEMTIME st, LPTSTR str, size_t str_size) { - sprintf_s(str, str_size, "%02i:%02i:%02i", st.wHour, st.wMinute, st.wSecond); + _stprintf_s(str, str_size, TEXT("%02i:%02i:%02i"), st.wHour, st.wMinute, st.wSecond); } /** @@ -266,12 +298,16 @@ // // Chemin de recherche pour le récursif _stprintf_s(chemin, _countof(chemin), TEXT("%s\\*"), szDir); - for (h = FindFirstFile(chemin, &w32fs); - h != INVALID_HANDLE_VALUE && next != 0; - next = FindNextFile(h, &w32fs)) { - if (w32fs.cFileName[0] == TEXT('.') && w32fs.cFileName[1] == 0 || - w32fs.cFileName[0] == TEXT('.') && w32fs.cFileName[1] == TEXT('.') && w32fs.cFileName[2] == 0 || - !(w32fs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + for ( + h = FindFirstFile(chemin, &w32fs); + h != INVALID_HANDLE_VALUE && next != 0; + next = FindNextFile(h, &w32fs) + ) { + if ( + w32fs.cFileName[0] == TEXT('.') && w32fs.cFileName[1] == 0 || + w32fs.cFileName[0] == TEXT('.') && w32fs.cFileName[1] == TEXT('.') && w32fs.cFileName[2] == 0 || + !(w32fs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + ) continue; // on part en récursif @@ -295,6 +331,8 @@ * \param[out] result vector de TCHAR contenant les fichiers répondant au nom passé en paramètre (ne pas oublier de libérer avec free) * \warning n'oubliez pas de libérer la mémoire allouée dans la fonction * \return le nombre de fichiers trouvés correspondant + * \todo Essayer de définir \p result comme étant std:vector plutôt que std::vector, ainsi + * le problème de la libération de mémoire à laquelle penser ne devrait plus se poser. **/ UINT FindFileRecur(LPCTSTR szDir, LPCTSTR szFile, std::vector *result) { WIN32_FIND_DATA w32fs; // Structure recevant les informations pour la recherche @@ -349,26 +387,19 @@ * \param[out] convertis chaîne de caractères convertie (à libérer après utilisation avec free() ) * \return le nombre de caractères convertis **/ -int ConvertUTF82Char(LPCSTR aconvertir, LPTSTR *convertis) { - int i, j, taille; // Itérateurs -#ifdef UNICODE - wchar_t c; // Caractères à convertir -#else - unsigned char c; // Caractères à convertir -#endif - LPTSTR _tmp; // Chaîne temporaire +int ConvertUTF82Char(LPCSTR aconvertir, LPTSTR & convertis) { + UINT i, j; // Itérateurs + TCHAR c; // Caractères à convertir + UINT taille = strlen_T(aconvertir); // La taille de la chaîne résultante est forcément plus courte + LPTSTR _tmp = STK_ALLOC(TCHAR, taille+1); // Chaîne temporaire - taille = strlen(aconvertir); // La taille de la chaîne résultante est forcément plus courte - _tmp = (LPTSTR)malloc(sizeof(TCHAR)*(taille + 1)); - for( i=0, j=0; i= 0xE0) { // Permet de prévenir que la chaîne ne peut pas être convertie, // car il faudrait plus de 8 bits pour produire le caractère - free(_tmp); return i; } #endif @@ -384,9 +415,8 @@ } _tmp[j] = 0; - *convertis = (LPTSTR)malloc(sizeof(wchar_t)*(j + 1)); - _tcscpy_s(*convertis, j+1, _tmp); - free(_tmp); + convertis = (LPTSTR)malloc(sizeof(wchar_t)*(j + 1)); + _tcscpy_s(convertis, j+1, _tmp); return i; } @@ -398,13 +428,10 @@ * \param[out] convertis chaîne de caractères convertie (à libérer après utilisation avec free() ) * \return le nombre de caractères convertis **/ -int ConvertChar2UTF8(LPCSTR aconvertir, char **convertis) { - int taille = strlen(aconvertir)+1; - LPTSTR temp = (LPTSTR)malloc(2*taille); - strcpy_T(temp, taille, aconvertir); - int ret = ConvertChar2UTF8(temp, convertis); - free(temp); - return ret; +int ConvertChar2UTF8(LPCSTR aconvertir, LPSTR & convertis) { + COPY_STR_ON_STACK(WCHAR, temp, aconvertir, taille); + + return ConvertChar2UTF8(temp, convertis); } /** @@ -414,14 +441,20 @@ * \param[out] convertis chaîne de caractères convertie (à libérer après utilisation avec free() ) * \return le nombre de caractères convertis **/ -int ConvertChar2UTF8(LPCWSTR aconvertir, char **convertis) { - int i, j, taille; // Itérateurs - LPSTR _tmp; // Chaîne de carastères temporaire - TCHAR c; // Caractère à convertir +int ConvertChar2UTF8(LPCWSTR aconvertir, LPSTR & convertis) +{ +#if 0 // expérimental + UINT taille = WideCharToMultiByte(CP_UTF8, 0, aconvertir, -1, NULL, 0, NULL, NULL); - taille = _tcslen(aconvertir); - _tmp = (LPSTR)malloc(taille*4+1);// La taille max de la chaîne est de 4 octets par caractères original - + convertis = reinterpret_cast(malloc(taille)); + taille = WideCharToMultiByte(CP_UTF8, 0, aconvertir, -1, convertis, taille, NULL, NULL); + return taille; +#else + UINT i, j; // Itérateurs + WCHAR c; // Caractère à convertir + UINT taille = strlen_T(aconvertir); + LPSTR _tmp = STK_ALLOC(CHAR, taille*4+1); // Chaîne de carastères temporaire (la taille max de la + // chaîne est de 4 octets par caractère original) for( i=0, j=0; i(&aconvertir), + 1, _tmp, _countof(_tmp), NULL, NULL); + + _tmp[taille] = 0; // zéro terminateur + convertis = reinterpret_cast(malloc(taille+1)); + strcpy_T(convertis, taille+1, _tmp); + return taille; +#else int j=0; // Itérateur - LPSTR _tmp; // Chaîne de caractères temporaire + CHAR _tmp[5]; // Chaîne de caractères temporaire - _tmp = (LPSTR)malloc(5);// La taille max de la chaîne est de 4 octets par caractères original - if (aconvertir <= 0x7F) _tmp[j++] = (char)aconvertir; else if (aconvertir <= 0x7FF) { @@ -480,9 +526,9 @@ } _tmp[j] = 0; - *convertis = (LPSTR)malloc(j+1); - strcpy_s(*convertis, j+1, _tmp); - free(_tmp); + convertis = (LPSTR)malloc(j+1); + strcpy_s(convertis, j+1, _tmp); return j; +#endif } Modifié: trunk/utils.h =================================================================== --- trunk/utils.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/utils.h 2009-01-10 16:58:21 UTC (rev 163) @@ -175,10 +175,12 @@ /** @} */ // fin de A2tmacros -/** @defgroup strcpy_T Copies de chaînes entre CHAR / WCHAR / TCHAR - * Ces fonctions assurent la copie depuis des chaînes de caractères de type TCHAR - * depuis ou vers des chaînes de caractères CHAR ou WCHAR. - * Elles ont toutes le même nom car elles devraient pouvoir être discriminérs par +// ---------------------------------------------------------------------------- + +/** @defgroup strcpy_T Copies de chaînes entre \p CHAR / \p WCHAR / \p TCHAR + * Ces fonctions assurent la copie depuis des chaînes de caractères de type \p TCHAR + * depuis ou vers des chaînes de caractères \p CHAR ou \p WCHAR. + * Elles ont toutes le même nom car elles devraient pouvoir être discriminées par * leurs arguments en C++, épargnant ainsi au programmeur d'avoir à faire le choix * lui-même. * @@ -243,7 +245,197 @@ /** @} */ // fin de strcpy_T +// ---------------------------------------------------------------------------- + +/** @defgroup strcat_T concaténation de chaînes entre \p CHAR / \p WCHAR / \p TCHAR + * Ces fonctions assurent la concaténation depuis des chaînes de caractères de type + * \p TCHAR depuis ou vers des chaînes de caractères \p CHAR ou \p WCHAR. + * Elles ont toutes le même nom car elles devraient pouvoir être discriminées par + * leurs arguments en C++, épargnant ainsi au programmeur d'avoir à faire le choix + * lui-même. + * + * \note Essayer quand même d'éviter les copies inutiles entre types différents, + * car on peut présumer que les fonctions \p MultiByteToWideChar et + * \p WideCharToMultiByte que cela appelle indirectement consomment relativement + * plus de ressources que celles impliquées au cours d'une copie simple. + * @{ + **/ + /** + * Version CHAR -> CHAR (alias de \p strcat_s). + * + * \param[in] pSrc Pointeur sur la chaîne source (CHAR) + * \param[in] nSizDst Taille du tampon de destination + * \param[in] pDst Pointeur sur le tampon de destination (CHAR) + **/ +inline errno_t strcat_T(LPSTR pDst, UINT nSizDst, LPCSTR pSrc) { + return strcat_s(pDst, nSizDst, pSrc);} + +/** + * Version WCHAR -> WCHAR (alias de \p wcscat_s). + * + * \param[in] pSrc Pointeur sur la chaîne source (WCHAR) + * \param[in] nSizDst Taille du tampon de destination + * \param[in] pDst Pointeur sur le tampon de destination (WCHAR) + **/ +inline errno_t strcat_T(LPWSTR pDst, UINT nSizDst, LPCWSTR pSrc) { + return wcscat_s(pDst, nSizDst, pSrc);} + +/** + * Version CHAR -> WCHAR (utilise \p MultiByteToWideChar). + * + * \param[in] pSrc Pointeur sur la chaîne source (CHAR) + * \param[in] nSizDst Taille du tampon de destination + * \param[in] pDst Pointeur sur le tampon de destination (WCHAR) + **/ +errno_t strcat_T(LPWSTR pDst, UINT nSizDst, LPCSTR pSrc); + +/** + * Version WCHAR -> CHAR (utilise \p WideCharToMultiByte). + * + * \param[in] pSrc Pointeur sur la chaîne source (WCHAR) + * \param[in] nSizDst Taille du tampon de destination + * \param[in] pDst Pointeur sur le tampon de destination (CHAR) + **/ +errno_t strcat_T(LPSTR pDst, UINT nSizDst, LPCWSTR pSrc); + +/** + * Version template, utilisable uniquement si la taille est dérivable de la destination. + * Cette version, à l'instar de celles de Microsoft sur les fonctions sécurisées de + * traitement de chaînes, permettent de se dispenser de fournir un décompte de la taille + * du tampon de destination si celle-ci peut en être dérivée (c'est-à-dire, si la + * destination est un tableau réel et non pas un pointeur). + * + * \param[in] pSrc Pointeur sur la chaîne source + * \param[out] szDst Tampon (tableau) de destination recevant la valeur copiée + **/ +template + inline errno_t strcat_T(TD (&szDst)[S], const TS * pSrc) { + return strcat_T(szDst, S, pSrc); } + +/** @} */ // fin de strcat_T + +// ---------------------------------------------------------------------------- + +/** @defgroup strlen_T Prendre la longueur d'une chaîne de caractères \p CHAR / \p WCHAR / \p TCHAR + * Ces fonctions comptent le nombre de caractères d'une chaîne, quelque soit le type + * de caractère inclus dans la chaîne. + * Elles ont toutes le même nom car elles devraient pouvoir être discriminées par + * leur arguments en C++, épargnant ainsi au programmeur d'avoir à faire le choix + * lui-même, et aussi elles facilitent leur usage dans un "template". + * + * Accessoirement, elles retournent aussi un type \p UINT (plutôt que \p size_t), évitant ainsi + * des cast de type ou des warnings agaçants. + * @{ + **/ + +/** + * Longueur d'une chaîne de caractères, version \p CHAR. + * + * \param[in] pszStr Pointeur sur la chaîne + **/ +inline UINT strlen_T(LPCSTR pszStr) { + return (UINT)strlen(pszStr);} + +/** + * Longueur d'une chaîne de caractères, version \p WCHAR. + * + * \param[in] pszStr Pointeur sur la chaîne + **/ +inline UINT strlen_T(LPCWSTR pszStr) { + return (UINT)wcslen(pszStr);} + +/** @} */ // fin de strlen_T + +// ---------------------------------------------------------------------------- + +/*! \def WCHAR2TCHAR + * Conversion "à la volée" d'une chaîne WCHAR vers une chaîne TCHAR. + * Macro à utiliser lorsque la conversion doit impérativement se faire + * au milieu d'une expression, et qu'on ne peut donc pas créer de variable + * intermédiaire. Dans tous les autres cas, il vaut mieux passer par une + * variable intermédiaire. + * L'allocation mémoire intermédiaire est néanmoins + * automatiquement libérée après évaluation de l'expression. + **/ +#ifdef _UNICODE + #define WCHAR2TCHAR(str) str +#else + inline std::auto_ptr WChar2Char(LPCWSTR pszStr) + { + UINT nLen = strlen_T(pszStr)+1; + std::auto_ptr pszRes(new CHAR[nLen]); + + strcpy_T(pszRes.get(), nLen, pszStr); + return pszRes; + } + #define WCHAR2TCHAR(str) WChar2Char(str).get() +#endif + +/** + * Macro d'allocation d'un tableau de \p taille éléments de type \p type sur la pile, + * en tirant parti des particularités de la fonction système \p _alloca. + * Permet un effet similaire à celui produit par l'extension non standard permise sur + * les compilateurs de type GCC, à savoir de pouvoir définir un tableau à l'intérieur + * d'une fonction, en utilisant un terme variable dans la taille du tableau. + * + * Par rapport à une allocation sur le tas (heap) avec \p malloc ou \p new, les + * avantages sont les suivants : + * - Traitement infiniment plus rapide (quelques instructions machine seulement) + * - Pas besoin de \p free ou \p delete, la destruction est implicite à la fin de la + * fonction. + * + * Pour ce qui est des inconvénients : + * - Usage strictement limité au corps d'une fonction : pas question de retourner + * le résultat. + * - Ne devrait pas être utilisé dans une boucle, à moins qu'il soit clair que le + * nombre d'appels sera très réduit : les allocations successives ne seraient pas + * libérées avant la sortie de la fonction. + * - La taille de l'allocation doit rester limitée à ce qui pourrait se déclarer en + * tant que variable locale (sinon, risque de débordement de la pile) + * + * Exemple : \code + * int taille=16; + * wchar_t * buffer = STK_ALLOC(wchar_t, taille); + * \endcode + * Ceci est à peu près équivalent à cette syntaxe, qui serait valide sous GCC : \code + * int taille=16; + * wchar_t buffer[taille]; + * \endcode + * \param[in] type Type des éléments du tableau + * \param[in] taille Nombre d'éléments à allouer +**/ +#define STK_ALLOC(type, taille) reinterpret_cast(_alloca((taille)*sizeof(type))) + +/** + * Macro à insérer dans le corps d'une fonction C++, et qui permet de générer + * une copie allouée sur la pile d'une chaîne de caractères, cette copie + * pouvant faire l'objet d'une transformation \p CHAR / \p WCHAR / \p TCHAR + * éventuelle au passage. + * \param[in] type nom d'un type de données qui définit un caractère + * \param[in] dest est le nom du pointeur sur la chaîne destination (copiée) + * \param[in] source est le nom de la chaîne à copier + * \param[in] taille est le nom d'une variable de type \p UINT qui sera créée + * et qui recevra la taille de la chaîne + 1. + * \note Cette macro ne peut **pas** devenir une fonction "inline", en raison du + * comportement très particulier de la fonction \p _alloca incluse. + **/ +#define COPY_STR_ON_STACK(type, dest, source, taille) \ + UINT taille = strlen_T(source)+1; \ + type * dest = STK_ALLOC(type, taille); \ + strcpy_T(dest, taille, source) + +// ---------------------------------------------------------------------------- + +#ifdef _UNICODE + typedef std::wstring tstring; //!< Alias "TCHAR" pour \p string ou \p wstring +#else + typedef std::string tstring; //!< Alias "TCHAR" pour \p string ou \p wstring +#endif + +// ---------------------------------------------------------------------------- + +/** * Structure pour la sauvegarde de la position des fenêtres **/ struct WindowPos { @@ -335,7 +527,7 @@ * \param[out] str chaîne de caractères résultant * \param[in] str_size longeur max de la chaîne de caractères **/ -void TimeToStr(SYSTEMTIME st, char *str, size_t str_size); +void TimeToStr(SYSTEMTIME st, LPTSTR str, size_t str_size); /** * Conversion temps GMT en temps local @@ -438,7 +630,7 @@ * \param[out] convertis chaîne de carastères convertie * \return le nombre de caractères convertis **/ -int ConvertUTF82Char(LPCSTR aconvertir, LPTSTR *convertis); +int ConvertUTF82Char(LPCSTR aconvertir, LPTSTR & convertis); /** * Convertir une chaine de caractères en UTF-8 @@ -447,7 +639,7 @@ * \param[out] convertis chaîne de caractères convertie * \return le nombre de caractères convertis **/ -int ConvertChar2UTF8(LPCWSTR aconvertir, LPSTR *convertis); +int ConvertChar2UTF8(LPCWSTR aconvertir, LPSTR & convertis); /** * Convertir une chaine de caractères en UTF-8 @@ -456,7 +648,7 @@ * \param[out] convertis chaîne de caractères convertie * \return le nombre de caractères convertis **/ -int ConvertChar2UTF8(LPCSTR aconvertir, LPSTR *convertis); +int ConvertChar2UTF8(LPCSTR aconvertir, LPSTR & convertis); /** * Convertir un caractère en UTF-8 @@ -464,5 +656,8 @@ * \param[in] aconvertir chaîne de caractères contenant éventuellement des caractères devant être encodés en UTF-8 * \param[out] convertis chaîne de caractères convertie * \return le nombre de caractères convertis + * \note \p aconvertir est de type \p UINT32 car : + * - TCHAR pose des problèmes étant donné qu'il s'agit d'une valeur *signée* + * - La fonction est capable de convertir des caractères codés sur plus de 16 bits **/ -int ConvertChar2UTF8(TCHAR aconvertir, LPSTR *convertis); +int ConvertChar2UTF8(UINT32 aconvertir, LPSTR & convertis); Modifié: trunk/xml.cpp =================================================================== --- trunk/xml.cpp 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/xml.cpp 2009-01-10 16:58:21 UTC (rev 163) @@ -42,7 +42,7 @@ CXMLElement::CXMLElement(IXMLDOMElement * element) : m_ele(element) { -// myprintf(L"élément contruit\n"); +// myprintf(TEXT("élément contruit\n")); } /** @@ -50,7 +50,7 @@ **/ CXMLElement::~CXMLElement() { -// myprintf(L"élément détruit\n"); +// myprintf(TEXT("élément détruit\n")); } /** @@ -94,7 +94,7 @@ CXMLNode::CXMLNode(IXMLDOMNode * element) : m_node(element) { -// myprintf(L"noeud construit\n"); +// myprintf(TEXT("noeud construit\n")); } /** @@ -102,7 +102,7 @@ **/ CXMLNode::~CXMLNode() { -// myprintf(L"noeud détruit\n"); +// myprintf(TEXT("noeud détruit\n")); } /** @@ -111,7 +111,7 @@ * \param[in] nom nom de l'élément recherché * \return la valeur recherchée **/ -int CXMLNode::getInt(const wchar_t * nom) +int CXMLNode::getInt(LPCWSTR nom) { int rep = 0; // Valeur de retour CComPtr pChildList; // Liste des enfants @@ -155,19 +155,12 @@ * \param[in] nom nom de l'élément recherché * \return la valeur recherchée **/ -int CXMLNode::getInt(const char * nom) +int CXMLNode::getInt(LPCSTR nom) { // Utilise la fonction UNICODE pour traiter celle-ci + COPY_STR_ON_STACK(WCHAR, buffer, nom, taille); - int taille = strlen(nom)+1, - ret; - wchar_t *buffer = new wchar_t[taille]; - ZeroMemory(buffer, taille); - strcpy_T(buffer, taille, nom); - - ret = this->getInt(buffer); - delete [] buffer; - return ret; + return getInt(buffer); } @@ -175,10 +168,10 @@ * Recherche la valeur textuelle associée à la clé indiquée * * \param[in] nom nom de la clé recherchée - * \param[out] str valeur retournée (attention, n'alloue pas de mémoire, celle-ci dois déjà être allouée) + * \param[out] str valeur retournée (attention, n'alloue pas de mémoire, celle-ci doit déjà être allouée) * \param[in] size longueur du tableau de caractères (\a str) **/ -void CXMLNode::getStr(const wchar_t * nom, wchar_t * str, size_t size) +void CXMLNode::getStr(LPCWSTR nom, LPWSTR str, UINT size) { CComPtr pChildList; // Liste des enfants @@ -216,37 +209,32 @@ * Recherche la valeur textuelle associée à la clé indiquée * * \param[in] nom nom de la clé recherchée - * \param[out] str valeur retournée (attention, n'alloue pas de mémoire, celle-ci dois déjà être allouée) + * \param[out] str valeur retournée (attention, n'alloue pas de mémoire, celle-ci doit déjà être allouée) * \param[in] size longueur du tableau de caractères (\a str) **/ -void CXMLNode::getStr(const char * nom, char * str, size_t size) +void CXMLNode::getStr(LPCSTR nom, LPSTR str, UINT size) { - int taille = strlen(nom)+1; - wchar_t *buffer = new wchar_t[taille]; + COPY_STR_ON_STACK(WCHAR, buffer, nom, taille); - strcpy_T(buffer, taille, nom); - - this->getStr(buffer, str, size); - delete [] buffer; + getStr(buffer, str, size); } /** * Recherche la valeur textuelle associée à la clé indiquée * * \param[in] nom nom de la clé recherchée - * \param[out] str valeur retournée (attention, n'alloue pas de mémoire, celle-ci dois déjà être allouée) + * \param[out] str valeur retournée (attention, n'alloue pas de mémoire, celle-ci doit déjà être allouée) * \param[in] size longueur du tableau de caractères (\a str) **/ -void CXMLNode::getStr(const wchar_t * nom, char * str, size_t size) +void CXMLNode::getStr(LPCWSTR nom, LPSTR str, UINT size) { // Utilise la fonction UNICODE pour traiter celle-ci - wchar_t *buffer = new wchar_t[size]; + LPWSTR buffer = STK_ALLOC(WCHAR, size); ZeroMemory(buffer, size); - this->getStr(nom, buffer, size); + getStr(nom, buffer, size); strcpy_T(str, size, buffer); - delete [] buffer; } /** @@ -256,14 +244,11 @@ * \param[out] noeud noeud retourné si on l'a trouvé. * Attention, ne pas oublier de libérer la mémoire une fois utilisé **/ -void CXMLNode::getChildrenByName(const char *nom, CXMLNode **noeud) { - int taille = strlen(nom)+1; - wchar_t *buffer = new wchar_t[taille]; +void CXMLNode::getChildrenByName(LPCSTR nom, CXMLNode **noeud) +{ + COPY_STR_ON_STACK(WCHAR, buffer, nom, taille); - strcpy_T(buffer, taille, nom); - - this->getChildrenByName(buffer, noeud); - delete [] buffer; + getChildrenByName(buffer, noeud); } /** @@ -273,7 +258,7 @@ * \param[out] noeud noeud retourné si on l'a trouvé. * Attention, ne pas oublier de libérer la mémoire une fois utilisé **/ -void CXMLNode::getChildrenByName(const wchar_t *nom, CXMLNode **noeud) { +void CXMLNode::getChildrenByName(LPCWSTR nom, CXMLNode **noeud) { CComPtr pChildList; // Liste des enfants // Récupère les enfants @@ -316,7 +301,7 @@ { m_doc.CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER); -// myprintf(L"wrapper contruit\n"); +// myprintf(TEXT("wrapper contruit\n")); } /** @@ -324,7 +309,7 @@ **/ CXMLWrapper::~CXMLWrapper() { -// myprintf(L"wrapper détruit\n"); +// myprintf(TEXT("wrapper détruit\n")); } /** @@ -334,7 +319,7 @@ * \retval S_OK fichier chargé avec succès * \retval S_FALSE erreur lors du chargement du fichier **/ -HRESULT CXMLWrapper::charge(const wchar_t * nom) +HRESULT CXMLWrapper::charge(LPCWSTR nom) { CComVariant var; VARIANT_BOOL status; @@ -352,17 +337,11 @@ * \retval S_OK fichier chargé avec succès * \retval S_FALSE erreur lors du chargement du fichier **/ -HRESULT CXMLWrapper::charge(const char * nom) +HRESULT CXMLWrapper::charge(LPCSTR nom) { - int taille = strlen(nom)+1, - ret; - wchar_t *buffer = new wchar_t[taille]; - strcpy_T(buffer, taille, nom); + COPY_STR_ON_STACK(WCHAR, buffer, nom, taille); - ret = this->charge(buffer); - delete [] buffer; - - return ret; + return charge(buffer); } /** @@ -373,9 +352,9 @@ * \retval S_OK arbre initialisé avec succès * \retval S_FALSE erreur lors du chargement de l'arbre **/ -HRESULT CXMLWrapper::charge_xml(const wchar_t *xml) +HRESULT CXMLWrapper::charge_xml(LPCWSTR xml) { - // Convertie le wchar_t en BSTR + // Convertit le WCHAR en BSTR BSTR var = SysAllocString(xml); VARIANT_BOOL status; @@ -390,7 +369,7 @@ /** * Sauvegarde le contenu du XML dans un fichier **/ -HRESULT CXMLWrapper::sauvegarde(const wchar_t *nom) { +HRESULT CXMLWrapper::sauvegarde(LPCWSTR nom) { VARIANT var; VariantInit(&var); @@ -431,8 +410,8 @@ ref(rf) { LPSTR sztemp=0; - ConvertChar2UTF8(name, &sztemp); - sprintf_s(str, sztemp); + ConvertChar2UTF8(name, sztemp); + strcpy_T(str, sztemp); free(sztemp); ref.add_open(str); ref.send(); @@ -570,13 +549,13 @@ On remplace tout de même les caractères '&', '<' et '>' par des valeurs sûres * \return la valeur de send() **/ -int CXMLOutput::put(LPCSTR name, LPCSTR str) +int CXMLOutput::put(LPCSTR name, LPCWSTR str) { - unsigned char ch; - LPSTR buff = 0; + UINT ch; + LPSTR buff = 0; add_indent(); - ConvertChar2UTF8(name, &buff); + ConvertChar2UTF8(name, buff); add_open(buff); free(buff); buff=0; while ((ch = *str++)!=0) { @@ -585,7 +564,7 @@ case '<': add("<"); break; case '>': add(">"); break; default: - ConvertChar2UTF8(ch, &buff); + ConvertChar2UTF8(ch, buff); add(buff); free(buff); buff = 0; } @@ -595,6 +574,21 @@ } /** + * Stocke la chaine passée dans un nouvel élément + * + * \param[in] name nom de l'élément devant être créé + * \param[in] str valeur de l'élément. + On remplace tout de même les caractères '&', '<' et '>' par des valeurs sûres + * \return la valeur de send() + **/ +int CXMLOutput::put(LPCSTR name, LPCSTR str) +{ + COPY_STR_ON_STACK(WCHAR, buffer, str, taille); + + return put(name, buffer); +} + +/** * Stocke l'entier passé dans un nouvel élément * * \param[in] name nom de l'élément Modifié: trunk/xml.h =================================================================== --- trunk/xml.h 2009-01-07 15:13:13 UTC (rev 162) +++ trunk/xml.h 2009-01-10 16:58:21 UTC (rev 163) @@ -43,15 +43,15 @@ CXMLNode(IXMLDOMNode * node); ~CXMLNode(); - int getInt(const wchar_t * nom); - int getInt(const char *nom); + int getInt(LPCWSTR nom); + int getInt(LPCSTR nom); - void getStr(const wchar_t * nom, char * str, size_t size); - void getStr(const char * nom, char * str, size_t size); - void getStr(const wchar_t * nom, wchar_t * str, size_t size); + void getStr(LPCWSTR nom, LPSTR str, UINT size); + void getStr(LPCSTR nom, LPSTR str, UINT size); + void getStr(LPCWSTR nom, LPWSTR str, UINT size); - void getChildrenByName(const wchar_t *nom, CXMLNode **noeud); - void getChildrenByName(const char *nom, CXMLNode **noeud); + void getChildrenByName(LPCWSTR nom, CXMLNode **noeud); + void getChildrenByName(LPCSTR nom, CXMLNode **noeud); }; /** @@ -85,13 +85,13 @@ CXMLElement getDocElement(); - HRESULT charge(const wchar_t * nom); - HRESULT charge(const char * nom); + HRESULT charge(LPCWSTR nom); + HRESULT charge(LPCSTR nom); // Document XML entier - HRESULT charge_xml(const wchar_t * xml); + HRESULT charge_xml(LPCWSTR xml); // Sauvegarde le fichier XML - //HRESULT sauvegarde(const wchar_t * nom); + //HRESULT sauvegarde(LPCWSTR nom); }; // ---------------------------------------------------------------------------- @@ -133,6 +133,7 @@ {return fop!=NULL;} int put(LPCSTR name, int val); // Ajout d'un entier int put(LPCSTR name, LPCSTR str); // Ajout d'une chaîne + int put(LPCSTR name, LPCWSTR str); // Ajout d'une chaîne static LPCSTR fmt(LPCSTR fmt, ...); // Utilitaire de reformatage ~CXMLOutput(); // (le destructeur ferme le fichier) }; From pouchintv-dev at baysse.fr Sun Jan 11 00:43:05 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sun, 11 Jan 2009 00:43:05 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r164 - trunk Message-ID: <20090110234305.3F39E5F427@mail.baysse.fr> Author: gingko Date: 2009-01-11 00:43:04 +0100 (dim, 11 jan 2009) New Revision: 164 Modified: trunk/channels.cpp trunk/graph.cpp trunk/ini.cpp trunk/ini.h trunk/main.cpp trunk/rendering.h Log: main.cpp, channels.cpp, ini.cpp, rendering.h : * Modification du réglage de volume (d'après un patch proposé par MatMaul dans le forum) pour lui donner une variation logarithmique d'une part, et une progression par pas de 5 d'autre part. ini.cpp : * Suppression de la distinction "Debug" / "Config" dans le fichier "config.ini" (remplacé par une option de configuration, voir plus loin) * Ajout d'un test vérifiant la présence d'un debugger, et dans l'affirmative, modifiant les noms des items de configuration utilisés pour les codecs (ceci permettant de les configurer spécifiquement pour éviter les problèmes liés aux codecs propriétaires protégés contre le debugging) * Correction d'un bug dans "remplit_villes", qui faisait que toutes les villes étaient ajoutées deux fois dans la liste de sélection. * RcdataResource::Extraction : correction d'une petite erreur introduite par moi dans la livraison précédente. main.cpp, ini.h, ini.cpp, graph.cpp : * Ajout d'une option de configuration "--prefix", devant être suivie d'un argument. Cet argument est une chaîne préfixe qui sera ajoutée au début des noms de tous les fichiers de configuration (config.ini, canaux.ini, chaines.xml, programmes.xml), permettant ainsi de faire des tests de configuration sans affecter la configuration principale. Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2009-01-10 16:58:21 UTC (rev 163) +++ trunk/channels.cpp 2009-01-10 23:43:04 UTC (rev 164) @@ -25,6 +25,7 @@ * See http://pouchintv.baysse.fr/ for updates. */ +#include #include "base.h" #include "channels.h" #include "main.h" @@ -492,6 +493,11 @@ { CComQIPtr pBas(pGraph); - if (pBas) - pBas->put_Volume(volume); + if (pBas) { + int nDbVolume = -8000; + + if (volume > 0) + nDbVolume = (int)((log10(1.0*volume)-2)*5000); + pBas->put_Volume(nDbVolume); + } } Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2009-01-10 16:58:21 UTC (rev 163) +++ trunk/graph.cpp 2009-01-10 23:43:04 UTC (rev 164) @@ -965,7 +965,7 @@ if (FAILED(hr)) return erreur( TEXT("Le grabber n'a pas pu être connecté à la carte TNT, ") - TEXT("veuillez effacer \"config.ini\" et redémarrer"), hr); + TEXT("veuillez effacer \"%s%s\" et redémarrer"), hr, prefix_conf, config_file); filtrePrec.Release(); enregistrements_actuels[i].query(pGrabber); @@ -982,7 +982,7 @@ if (FAILED(hr)) return erreur( TEXT("Le grabber n'a pas pu être connecté au démultiplexeur, ") - TEXT("veuillez effacer \"config.ini\" et redémarrer"), hr); + TEXT("veuillez effacer \"%s%s\" et redémarrer"), hr, prefix_conf, config_file); } } Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-01-10 16:58:21 UTC (rev 163) +++ trunk/ini.cpp 2009-01-10 23:43:04 UTC (rev 164) @@ -104,6 +104,9 @@ /// Répertoire pour la sauvegarde des paramètres (Dossier App Data) TCHAR pouchindir_conf[MAX_PATH]; +/// Préfixe optionnel aux noms de fichiers de configuration +TCHAR prefix_conf[32] = TEXT(""); + /** * Motif pour le nom des fichiers pour les enregistrements, ainsi que la valeur par défaut
@@ -174,13 +177,16 @@
 #define freq_canal(x) (x * 8000 + freq_offset)
 
 // ====================================================================================
+
+TCHAR config_file[]						= TEXT("config.ini");	///< Nom du fichier de configuration
+
+// ====================================================================================
 // Sections dans le fichier de config
 // ====================================================================================
-static TCHAR config_file[]				= TEXT("config.ini");					///< Nom du fichier de configuration
-static TCHAR ini_config[]				= TEXT(IF_DEBUG_WE("Debug", "Config"));	///< Nom de la section contenant la configuration (en mode Debug)
-static TCHAR ini_filtre_MPEG2[]			= TEXT("Filtre MPEG2");
-static TCHAR ini_filtre_audio[]			= TEXT("Filtre audio");
-static TCHAR ini_filtre_ac3[]			= TEXT("Filtre AC3");
+static TCHAR ini_config[]				= TEXT("Config");		///< Nom de la section contenant la configuration
+static TCHAR ini_filtre_MPEG2[]			= TEXT("Filtre MPEG2\0(debug)");
+static TCHAR ini_filtre_audio[]			= TEXT("Filtre audio\0(debug)");
+static TCHAR ini_filtre_ac3[]			= TEXT("Filtre AC3\0(debug)");
 static TCHAR ini_nom_ville[]			= TEXT("Ville");
 static TCHAR ini_strict[]				= TEXT("Recherche stricte");
 static TCHAR ini_chaine_courante[]		= TEXT("Identifiant chaîne courante");
@@ -506,7 +512,7 @@
 			// Bloque la ressource en mémoire pour utilisation
 			LPBYTE RcdataRes = (LPBYTE)LockResource(hRcdataCharge);
 
-			if (RcdataRes == NULL) {
+			if (RcdataRes != NULL) {
 				// Tout s'est bien passé: on peut utiliser la resource
 				contenu = new BYTE[taille + 1];
 				ZeroMemory(contenu, taille + 1);
@@ -565,9 +571,9 @@
 	FILE *	fop;
 
 	if (_tfopen_s(&fop, fileName, TEXT("wb")))
-		myprintf(TEXT("Fichier canaux.ini => Erreur écriture\n"));
+		myprintf(TEXT("Fichier %s => Erreur écriture\n"), scan_ini);
 	else {
-		myprintf(TEXT("Fichier canaux.ini => Création\n"));
+		myprintf(TEXT("Fichier %s => Création\n"), scan_ini);
 		fputs(canaux, fop);
 		fclose(fop);
 	}
@@ -1213,7 +1219,7 @@
 #if USE_CONSOLE==1
 	save_config_winpos(ini_position_console, GetConsoleWindow());
 #endif // #if USE_CONSOLE==1
-	save_config_int(ini_volume, (volumeCourant + 10000) / 100);
+	save_config_int(ini_volume, volumeCourant);
 	save_config_assoc(ini_epg_typerecvideo, aEpgRecVideo, epg_typerecvideo);
 	save_config_assoc(ini_epg_typerecaudio, aEpgRecAudio, epg_typerecaudio);
 	save_config_raccourcis();
@@ -1427,31 +1433,48 @@
  **/
 void load_config(void)
 {
-	TCHAR chemin_config[MAX_PATH];
+	NomFichierConf	chemin_config(config_file);
 
-	strcpy_T(chemin_config, pouchindir_conf);
-	strcat_T(chemin_config, config_file);
+	strcpy_T(confPathName, (LPCTSTR)chemin_config);
 
-	strcpy_T(confPathName, chemin_config);
-
 	// Recherche si on a un fichier de config dans AppData
 	load_config_str(ini_tuner, nom_tuner, _countof(nom_tuner));
 	if (nom_tuner[0] == 0) {
 		// Pas de tuner trouvé. On recherche dans le dossier courant
 		strcpy_T(confPathName, pouchindir_prog);
+		strcat_T(confPathName, prefix_conf);
 		strcat_T(confPathName, config_file);
 
 		load_config_str(ini_tuner, nom_tuner, _countof(nom_tuner));
 		// Vérifie si on a une réponse
 		if (nom_tuner[0] == 0)
 			// Comme fichier config.ini n'existe pas non plus, restauration du chemin vers %AppData%
-			strcpy_T(confPathName, chemin_config);
+			strcpy_T(confPathName, (LPCTSTR)chemin_config);
 		else
 			// la config du tuner a été trouvée dans le répertoire de PTVM
 			// On change le répertoire de config vers celui du programme
 			strcpy_T(pouchindir_conf, pouchindir_prog);
 	}
 
+	static bool bFirstCall = true;
+
+	if (bFirstCall) {
+		// Ceci est exécuté seulement une fois au premier appel de la fonction :
+		if (IsDebuggerPresent()) {
+			// Présence d'un debugger : on utilise des noms de fichiers de configuration
+			// distincts pour les codecs, afin de pouvoir, dans ces conditions, éviter
+			// les codecs propriétaires protégés qui bloquent l'application.
+
+			// Pour se faire, on écrit juste un espace à la place du zéro terminateur
+			// du nom concerné, pour "ouvrir" l'accès au mot "(debug)" qui se trouve
+			// derrière.
+			ini_filtre_MPEG2[strlen_T(ini_filtre_MPEG2)] = TCHAR(' ');
+			ini_filtre_audio[strlen_T(ini_filtre_audio)] = TCHAR(' ');
+			ini_filtre_ac3[strlen_T(ini_filtre_ac3)] = TCHAR(' ');
+		}
+		bFirstCall = false;
+	}
+
 	load_config_str(ini_receiver, nom_receiver, _countof(nom_receiver));
 	load_config_str(ini_filtre_MPEG2, filtreMPEG2, _countof(filtreMPEG2));
 	offset_tuner			= load_config_int(ini_offset_tuner, 0);
@@ -1491,7 +1514,7 @@
 	video_pan_mode			= (PanModes)load_config_assoc(ini_video_pan_mode, aPanModeTable, pm_Normal);
 
 	zoom_ratio				= load_config_int(ini_zoom_ratio, 100);
-	volumeCourant			= load_config_int(ini_volume, 100) * 100 - 10000;
+	volumeCourant			= load_config_int(ini_volume, 100);
 
 	epg_typerecvideo		= load_config_assoc(ini_epg_typerecvideo, aEpgRecVideo, 0);
 	epg_typerecaudio		= load_config_assoc(ini_epg_typerecaudio, aEpgRecAudio, 0);
@@ -1507,7 +1530,7 @@
 void remplit_villes(HWND hItm)
 {
 	// nombre de caractères à ajouter pour toutes les contenir en une fois
-	const int delta = 1024;
+	const int delta = 0x1000;
 	// nombre de caractères pour contenir les sections
 	DWORD longueur = delta;
 	// contient toutes les sections du fichier INI
@@ -1518,8 +1541,8 @@
 
 	// Détermine la taille de la chaîne devant contenir toutes les sections
 	// car sinon, si le fichier INI contient trop de sections, on ne le lit pas les dernières
-	while(GetPrivateProfileSectionNames(strings, longueur, fileName) == longueur-2) {
-		// la taille du tableau est trop petit, on l'agrandie
+	while (GetPrivateProfileSectionNames(strings, longueur, fileName) == longueur-2) {
+		// la taille du tableau est trop petite, on l'agrandit
 		delete [] strings;
 		longueur += delta;
 		strings = new TCHAR[longueur];
@@ -1533,17 +1556,13 @@
 	while (*p != 0) {
 		// On ignore la catégorie «Général» car elle permet de définir des informations
 		// dans le fichier des canaux.ini
-		if (_tcscmp(TEXT("Général"), p)) {
+		if (_tcscmp(TEXT("Général"), p))
 			// Ajoute l'entrée à la liste déroulante
 			SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)p);
-		}
-		SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)p);
 
 		// trouve le prochain 0
-		while (*p != 0) {
+		while (*p != 0)
 			p++;
-		}
-
 		p++;
 	}
 

Modifié: trunk/ini.h
===================================================================
--- trunk/ini.h	2009-01-10 16:58:21 UTC (rev 163)
+++ trunk/ini.h	2009-01-10 23:43:04 UTC (rev 164)
@@ -46,6 +46,12 @@
 /// Répertoire pour la sauvegarde des paramètres (Dossier App Data)
 extern TCHAR	pouchindir_conf[MAX_PATH];
 
+/// Préfixe optionnel aux noms de fichiers de configuration
+extern TCHAR	prefix_conf[32];
+
+/// Nom du fichier de configuration
+extern TCHAR	config_file[];
+
 /**
  * Listes des types de VMR disponibles
  **/
@@ -91,6 +97,7 @@
 
 	NomFichierConf(LPCTSTR pszBaseName) {
 		strcpy_T(str, pouchindir_conf);
+		strcat_T(str, prefix_conf);
 		strcat_T(str, pszBaseName);
 	}
 	operator LPCTSTR() const {
@@ -249,7 +256,7 @@
 		T *			pcar;
 
 		while ((pcar = find_invalid(nom)) != NULL)
-				*pcar = remplacement;
+			*pcar = remplacement;
 	}
 
 

Modifié: trunk/main.cpp
===================================================================
--- trunk/main.cpp	2009-01-10 16:58:21 UTC (rev 163)
+++ trunk/main.cpp	2009-01-10 23:43:04 UTC (rev 164)
@@ -838,7 +838,7 @@
 		}
 
 		if (!use_osd) {
-			_stprintf_s(str, TEXT("%s %i"), muted ? TEXT("Volume") : TEXT("Sourdine"), (volumeCourant+8000)/80);
+			_stprintf_s(str, TEXT("%s %i"), muted ? TEXT("Volume") : TEXT("Sourdine"), volumeCourant);
 			SendMessage(hMainStatus, SB_SETTEXT, 5, (LPARAM)str);
 		}
 	}
@@ -1293,7 +1293,7 @@
 	lcd.Mute(muted);
 #endif // #ifdef USE_LOGITECH_LCD
 
-	set_volume(muted ? -8000 : (volumeCourant < 0 ? volumeCourant : 0));
+	set_volume(muted ? 0 : volumeCourant);
 
 	if (pOSD)
 		pOSD->DisplayMute(muted);
@@ -1302,11 +1302,8 @@
 
 static void update_volume(bool augmente)
 {
-	if (augmente && volumeCourant < 0)
-		volumeCourant += 80;
-	else if (!augmente && volumeCourant > -8000)
-		volumeCourant -= 80;
-
+	volumeCourant += augmente ? 5 : -5;
+	volumeCourant = max(min(volumeCourant, 100), 0);
 	if (!muted)
 		set_volume(volumeCourant);
 
@@ -2211,6 +2208,7 @@
 	cmd_rects,
 	cmd_chaine,
 	cmd_help,
+	cmd_prefix
 };
 
 /// Structure regroupant les états décodés des options de ligne de commande
@@ -2248,7 +2246,8 @@
 		L"--recps",
 		L"--rects",
 		L"--ch",
-		L"--help"
+		L"--help",
+		L"--prefix"
 	};
 
 	CmdOptions * valeurs = new CmdOptions;
@@ -2258,20 +2257,16 @@
 		LPCWSTR arg = szArgList[i];
 
 		for (int j=0; j<_countof(szCmdLongOptions); j++) {
-			if (wcscmp (arg, szCmdLongOptions[j]) == 0) {
+			if (wcscmp(arg, szCmdLongOptions[j]) == 0) {
 				// Option trouvée. Traitement de l'option, et des paramètres supplémentaires si besoin
 
 				switch (j) {
-				case cmd_chaine: {
-					size_t iChaineLen		= wcslen(szArgList[i+1]);
-					LPWSTR cmdOptionTemp	= new WCHAR[iChaineLen+1];
-
+				case cmd_chaine:
 					// On récupère la valeur du canal ainsi passé
-					wcscpy_s(cmdOptionTemp, iChaineLen+1, szArgList[i+1]);
-					valeurs->nChaine = _wtoi(cmdOptionTemp);
-					i++;
-					delete [] cmdOptionTemp;
-					break; }
+					++i;
+					if (inChaine = _wtoi(szArgList[i]);
+					break;
 
 				case cmd_minimize:
 				case cmd_minimize_old:
@@ -2302,10 +2297,19 @@
 					valeurs->bRecTS = true;
 					break;
 
+				case cmd_prefix:
+					// Préfixe à ajouter aux noms des fichiers de configuration
+					++i;
+					if (i prefix_prot(szArgList[i], TCHAR('_'));
+
+						prefix_prot.Extract(prefix_conf, _countof(prefix_conf));
+					}
+					break;
+
 				default:
 					myprintf(TEXT("Erreur option %d : (%s:%d)"),
 						j, TEXT(__FILE__), __LINE__);
-					break;
 				}
 				break;
 			}

Modifié: trunk/rendering.h
===================================================================
--- trunk/rendering.h	2009-01-10 16:58:21 UTC (rev 163)
+++ trunk/rendering.h	2009-01-10 23:43:04 UTC (rev 164)
@@ -382,7 +382,7 @@
 	/// Affichage du volume sonore
 	/// \param[in] nCurrentVolume niveau de volume courant
 	void	DisplayVolume(long nCurrentVolume) {
-				cBotLeft.SetText(TEXT("Volume %i"), (nCurrentVolume+8000)/80);}
+				cBotLeft.SetText(TEXT("Volume %i"), nCurrentVolume);}
 
 	/// Affichage du zoom
 	/// \param[in] nZoomRatio zoom courant


From pouchintv-dev at baysse.fr  Sun Jan 11 20:56:22 2009
From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=)
Date: Sun, 11 Jan 2009 20:56:22 +0100 (CET)
Subject: [Pouchintv-dev] [PouchinTVMod] lolo_32 | r165 - in trunk: .
	BaseClasses Icones/Locales
Message-ID: <20090111195622.392535F41F@mail.baysse.fr>

Author: lolo_32
Date: 2009-01-11 20:56:21 +0100 (dim, 11 jan 2009)
New Revision: 165

Added:
   trunk/Icones/Locales/alsatic TV.bmp
Modified:
   trunk/
   trunk/BaseClasses/
   trunk/BaseClasses/baseclasses.vcproj
   trunk/LCD.cpp
   trunk/LCD.h
   trunk/atlbase_ptvm.h
   trunk/base.cpp
   trunk/base.h
   trunk/graph.cpp
   trunk/ini.cpp
   trunk/main.cpp
   trunk/main.h
   trunk/recprog.cpp
Log:
atlbase_ptvm.h:
  * ajout d'une nouvelle classe ATL

base.cpp:
  * correction de boggues dans le logs des messages

baseclasses.vcproj:
  * désactivation des messages d'avertissemrnt en cas de compilation en Debug_MBCS pour l'utilisation des fonctions sécurisées

graph.cpp, main.h, main.cpp:
  * la variable pour le fichier de log du graphe est maintenant locale à graph

ini.cpp:
  * correction d'une coquille empêchant la bonne sauvegarde des préférences des chaînes si on compile en mode MCBS

LCD.cpp, LCD.h:
  * remplacement des paramètres de fonctions du type wchar_t en TCHAR

recprog.cpp:
  * ajout d'un raccourcis clavier (touche Suppr) pour effacer un programme dans la liste

divers:
  * ajout de l'icône de la chaîne alsatic TV


Property changes on: trunk
___________________________________________________________________
Nom : svn:ignore
   - Debug
Release
Vista Debug
Vista Release
x64
chaines.xml
config.ini
pouchin.log
Pouchin TV.suo
Pouchin TV.ncb
Pouchin TV.vcproj.*
programmes.xml
.*.swp
version.txt
res.aps
PouchinTVMod*.exe
vstudio_edition.h
Debug_x64
Release_x64
version.h

   + Debug
Release
Vista Debug
Vista Release
x64
chaines.xml
config.ini
pouchin.log
Pouchin TV.suo
Pouchin TV.ncb
Pouchin TV.vcproj.*
programmes.xml
.*.swp
version.txt
res.aps
PouchinTVMod*.exe
vstudio_edition.h
Debug_x64
Release_x64
version.h
Release_SBCS
Debug_SBCS



Property changes on: trunk/BaseClasses
___________________________________________________________________
Nom : svn:ignore
   - Debug_Win32
Release_Win32
Debug_x64
Release_x64
baseclasses.vcproj.*
.*.swp

   + Debug_Win32
Release_Win32
Debug_x64
Release_x64
baseclasses.vcproj.*
.*.swp
Release_MBCS_Win32
Debug_MBCS_Win32


Modifié: trunk/BaseClasses/baseclasses.vcproj
===================================================================
--- trunk/BaseClasses/baseclasses.vcproj	2009-01-10 23:43:04 UTC (rev 164)
+++ trunk/BaseClasses/baseclasses.vcproj	2009-01-11 19:56:21 UTC (rev 165)
@@ -304,7 +304,7 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				AdditionalIncludeDirectories="."
-				PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
 				MinimalRebuild="true"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="3"

Ajouté: trunk/Icones/Locales/alsatic TV.bmp
===================================================================
(les fichiers binaires diffèrent)


Property changes on: trunk/Icones/Locales/alsatic TV.bmp
___________________________________________________________________
Nom : svn:mime-type
   + application/octet-stream

Modifié: trunk/LCD.cpp
===================================================================
--- trunk/LCD.cpp	2009-01-10 23:43:04 UTC (rev 164)
+++ trunk/LCD.cpp	2009-01-11 19:56:21 UTC (rev 165)
@@ -276,11 +276,11 @@
  * \param[in]  programme  le nom du programme
  * \param[in]  num        position du programme
  **/
-void CLcd::SetProgramme(const SYSTEMTIME &heure, const char *programme, const int num){
+void CLcd::SetProgramme(const SYSTEMTIME &heure, LPCTSTR programme, const int num){
 	if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici
 
 	TimeToStr(heure, this->programmes[num].heure, _countof(this->programmes[num].heure));
-	strncpy_s(this->programmes[num].prog, _countof(this->programmes[num].prog), programme, _countof(this->programmes[num].prog));
+	strcpy_T(this->programmes[num].prog, _countof(this->programmes[num].prog), programme);
 }
 
 
@@ -290,7 +290,7 @@
  * \param[in]  heure      la date/heure du déut du programme
  * \param[in]  programme  le nom du programme
  **/
-void CLcd::SetProgrammeActuel(const SYSTEMTIME &heure, const char *programme){
+void CLcd::SetProgrammeActuel(const SYSTEMTIME &heure, LPCTSTR programme){
 	if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici
 
 	SetProgramme(heure, programme, 0);
@@ -302,7 +302,7 @@
  * \param[in]  heure      la date/heure du déut du programme
  * \param[in]  programme  le nom du programme
  **/
-void CLcd::SetProgrammeSuivant(const SYSTEMTIME &heure, const char *programme){
+void CLcd::SetProgrammeSuivant(const SYSTEMTIME &heure, LPCTSTR programme){
 	if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici
 
 	SetProgramme(heure, programme, 1);

Modifié: trunk/LCD.h
===================================================================
--- trunk/LCD.h	2009-01-10 23:43:04 UTC (rev 164)
+++ trunk/LCD.h	2009-01-11 19:56:21 UTC (rev 165)
@@ -84,7 +84,7 @@
 	 * \param[in]  programme  le nom du programme
 	 * \param[in]  num        position du programme
 	 **/
-	void SetProgramme(const SYSTEMTIME &heure, const char *programme, const int num);
+	void SetProgramme(const SYSTEMTIME &heure, LPCTSTR programme, const int num);
 
 public:
 	enum {
@@ -115,14 +115,14 @@
 	 * \param[in]  heure      la date/heure du déut du programme
 	 * \param[in]  programme  le nom du programme
 	 **/
-	void SetProgrammeActuel(const SYSTEMTIME &heure, const char *programme);
+	void SetProgrammeActuel(const SYSTEMTIME &heure, LPCTSTR programme);
 	/**
 	 * Définit le nom et heure du programme suivant
 	 *
 	 * \param[in]  heure      la date/heure du déut du programme
 	 * \param[in]  programme  le nom du programme
 	 **/
-	void SetProgrammeSuivant(const SYSTEMTIME &heure, const char *programme);
+	void SetProgrammeSuivant(const SYSTEMTIME &heure, LPCTSTR programme);
 	/**
 	 * Fait passer le programme suivant en programme actuel
 	 **/

Modifié: trunk/atlbase_ptvm.h
===================================================================
--- trunk/atlbase_ptvm.h	2009-01-10 23:43:04 UTC (rev 164)
+++ trunk/atlbase_ptvm.h	2009-01-11 19:56:21 UTC (rev 165)
@@ -72,6 +72,8 @@
 		return p;}
 	void Release() {
 		IU* t=p; if (t) {p=NULL; t->Release();}}
+	IU* Detach() {
+		IU* pt = p; p = NULL; return pt; }
 	IU* operator = (const IU* q) {
 		Release(); p=q; p->AddRef(); return p;}
 	CComPtr & operator = (const CComPtr & r) {
@@ -120,3 +122,31 @@
 	~CComHeapPtr() {
 		Free();}
 };
+
+class CComBSTR
+{
+public:
+	BSTR m_str;
+
+	CComBSTR() : m_str(NULL) {
+		}
+	CComBSTR(LPCSTR pSrc) {
+		if (pSrc != NULL) {
+			int taille = MultiByteToWideChar(CP_ACP, 0, pSrc, -1, NULL, NULL);
+			m_str = ::SysAllocStringLen(NULL, taille);
+			if (m_str != NULL) {
+				int taille2 = MultiByteToWideChar(CP_ACP, 0, pSrc, -1, m_str, taille);
+				if (taille2 != taille)
+					::SysFreeString(m_str);
+			}
+		} else {
+			m_str = NULL;
+		}
+	}
+
+	operator BSTR() const {
+		return m_str; }
+	BSTR* operator&() {
+		return &m_str; }
+
+};

Modifié: trunk/base.cpp
===================================================================
--- trunk/base.cpp	2009-01-10 23:43:04 UTC (rev 164)
+++ trunk/base.cpp	2009-01-11 19:56:21 UTC (rev 165)
@@ -62,6 +62,7 @@
 		if (ch != TCHAR('\r'))
 			*pszPtr++ = ch==TCHAR('\n') ? TCHAR('/') : ch;
 	}
+	*pszPtr = 0;
 
 	GetLocalTime(&time);
 
@@ -115,7 +116,7 @@
 		pszErrBuf = pszNewErrBuf;
 
 		// Logue le message d'erreur
-		myprintferror(pszNewErrBuf);
+		myprintferror(buffer);
 	}
 
 	if (FAILED(hr) && hr!=lastRes) {

Modifié: trunk/base.h
===================================================================
--- trunk/base.h	2009-01-10 23:43:04 UTC (rev 164)
+++ trunk/base.h	2009-01-11 19:56:21 UTC (rev 165)
@@ -69,7 +69,7 @@
 // source. Voir commentaires dans le fichier atlbase_ptvm.h.
 #include "vstudio_edition.h"
 
-#ifndef COMPILER_EDITION_VCEXPRESS
+#if !defined(COMPILER_EDITION_VCEXPRESS)
 	#include 
 	#include 
 #else
@@ -97,6 +97,12 @@
 	#else
 		#define USE_CONSOLE 0
 	#endif
+#else
+	#if USE_CONSOLE == 1
+		// Pour la documentation de la variable avec Doxygen
+		#undef USE_CONSOLE
+		#define USE_CONSOLE 1
+	#endif
 #endif
 
 #include "console.h"

Modifié: trunk/graph.cpp
===================================================================
--- trunk/graph.cpp	2009-01-10 23:43:04 UTC (rev 164)
+++ trunk/graph.cpp	2009-01-11 19:56:21 UTC (rev 165)
@@ -41,6 +41,10 @@
 /// codecs qui n'ont pas été choisis en cas d'échec de ceux qui l'ont été.
 #define AUTO_RENDER 1
 
+#if LOG_DSHOW
+HANDLE			logFile = INVALID_HANDLE_VALUE;
+#endif // #if LOG_DSHOW
+
 CComPtr				pGraph;
 CComPtr				pEvents;
 

Modifié: trunk/ini.cpp
===================================================================
--- trunk/ini.cpp	2009-01-10 23:43:04 UTC (rev 164)
+++ trunk/ini.cpp	2009-01-11 19:56:21 UTC (rev 165)
@@ -66,7 +66,7 @@
 	{IDM_DELAYED_RECORD,	TEXT("Programmer les enregistrements"),			TEXT("Enreg Programmer"),	{false,	false,	false,	TEXT('P')}},
 	{IDM_RECORD_CHANNEL_PS,	TEXT("Enregistrer la chaîne en PS"),			TEXT("Enreg PS"),			{false,	true,	false,	VK_SPACE}},
 	{IDM_RECORD_CHANNEL_TS,	TEXT("Enregistrer la chaîne en TS"),			TEXT("Enreg TS"),			{false,	true,	false,	TEXT('T')}},
-	{IDM_SCREENSHOT,		TEXT("Capture d'écran"),						TEXT("Enreg Capure écran"),	{false,true,	false,	TEXT('X')}},
+	{IDM_SCREENSHOT,		TEXT("Capture d'écran"),						TEXT("Enreg Capure écran"),	{false,	true,	false,	TEXT('X')}},
 	{IDM_STOP_RECORD,		TEXT("Stopper l'enregistrement"),				TEXT("Enreg Stop immédiat"),{false,	true,	false,	VK_RETURN}},
 	{IDM_DELAYED_STOP,		TEXT("Arrêt différé des enregistrements"),		TEXT("Enreg Stop différé"),	{false,	false,	false,	TEXT('S')}},
 	// Volume/Son
@@ -81,10 +81,10 @@
 	{IDM_FULLSCREEN,		TEXT("Plein écran"),							TEXT("Aff Plein écran"),	{false,	false,	false,	VK_SPACE}},
 	{IDM_ZOOM,				TEXT("Zoomer"),									TEXT("Aff Zoomer"),			{true,	false,	false,	TEXT('Z')}},
 	{IDM_DEZOOM,			TEXT("Dézoomer"),								TEXT("Aff Dézoomer"),		{false,	false,	false,	TEXT('Z')}},
+	{IDM_DEFAULT_ZOOM,		TEXT("Restaure le zoom"),						TEXT("Aff Restaurer"),		{false,	false,	false,	TEXT('D')}},
 	{IDM_ALLWDT,			TEXT("Utiliser toute la largeur"),				TEXT("Aff Pleine largeur"),	{false,	false,	false,	TEXT('W')}},
 	{IDM_ALLHGT,			TEXT("Utiliser toute la hauteur"),				TEXT("Aff Pleine hauteur"),	{false,	false,	false,	TEXT('H')}},
 	{IDM_ETIRER,			TEXT("Étirer la vidéo"),						TEXT("Aff Étirer"),			{false,	false,	false,	TEXT('E')}},
-	{IDM_DEFAULT_ZOOM,		TEXT("Restaure le zoom/étirement"),				TEXT("Aff Restaurer"),		{false,	false,	false,	TEXT('D')}},
 
 	{IDM_ABOUT,             TEXT("Afficher la fenêtre des crédits"),		NULL,						{false,	true,	false,	VK_F1}},
 };
@@ -883,7 +883,7 @@
 		CXMLOpenChild oxmlc3(oxml, "Repetitions");
 
 		for (int j=0; j<7; j++)
-			oxml.put(oxml.fmt("%S", Tbl_DoW[j]), (programme.repetition & (1<wVKey == VK_DELETE)
+					SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_REMOVE, 0), 0);
 			}
 			break;
 


From pouchintv-dev at baysse.fr  Sat Jan 10 18:14:27 2009
From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=)
Date: Sat, 10 Jan 2009 18:14:27 +0100 (CET)
Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r163 - log changed
Message-ID: <20090110171427.A3E2B5F424@mail.baysse.fr>

Author: gingko
Date: 2009-01-10 17:58:21 +0100 (sam, 10 jan 2009)
Revision: 163 - Log changed 

New log:
  Finalisation des transformations de compatibilité TCHAR :
  * À peu près toutes les corrections possibles sont faites et vérifiées.
  * Le projet peut maintenant se compiler indifféremment en mode 8 bits et
    Unicode et s'exécuter correctement dans les deux modes.
  * Noter que j'ai fini par trouver un aménagement qui permet de stocker
    la plupart des noms de filtres dans des chaînes TCHAR. Il reste cependant
    quelques exceptions, signalées en commentaires.

  Pouchin TV.sln, Pouchin TV.vcproj :
  * Ajout des configurations Debug_SBCS et Release_SBCS (SBCS = Single Byte
    Character Set) permettant de compiler le projet avec des caractères
    simple octet.
  * Ces configurations se connectent au projet "BaseClasses" en mode
    Debug_MBCS ou Release_MBCS, ce qui en la circonstance ne devrait pas
    poser de problèmes.
  * Ces configurations se connectent au projet "tinyxml" en mode Debug ou
    Release (sachant que dans ce projet, ces modes correspondent
    actuellement au mode SBCS, et que la configuration Unicode devait
    déjà s'y adapter).

  graph.cpp :
  * Ajout des fonctions d'assistance "AddFilterToGraph" pour gérer les ajouts
    de filtres et ne plus dépendre du type de caractères utilisé pour les
    noms de filtres.

  utils.h, utils.cpp :
  * Ajout des fonctions utilitaires "strlen_T" et "strcat_T', qui se joignent aux
    fonctions "strcpy_T" précédemment ajoutées, pour un usage analogue.
  * Ajout d'un typedef "tstring" pour introduire l'utilisation à venir de
    chaînes de caractères "string" ou "wstring" de la bibliothèques STL,
    lesquelles dans de nombreux cas gagneraient à être utilisées plutôt que de
    faire des allocations "malloc/free" ou "new/delete" pour des chaînes de
    caractères (note : limiter quand même l'usage de ceci aux cas où c'est
    nécessaire).
  * Ajout d'une macro STK_ALLOC (exploitant la fonction système "_alloca") pour
    allouer des tableaux de taille dynamiquement calculée, à utiliser pour les
    allocations de mémoire raisonnablement petites et dont la durée de vie est
    limitée à un corps de fonction.
  * Ajout d'une macro COPY_STR_ON_STACK (exploitant STK_ALLOC) pour effectuer
    des copies de chaînes de caractères (avec transformation de largeur de
    caractères éventuelle) dont la durée de vie est limitée à un corps de fonction.
  * Quelques réorganisations dans les fonctions "ConvertUTF82Char", notamment
    en raison du fait qu'en configuration SBCS, l'une d'entre elle venait à
    s'appeler elle-même, amenant un plantage pour cause de débordement de pile.

  ini.h, ini.cpp :
  * Réactivation de la sauvegarde des informations de pistes audio et vidéo (à
    cause des problèmes posés avec les enregistrements programmés). On peut
    cependant continuer à tester en mettant à zéro la macro STREAMS_SAVE_ALL.
  * La structure "RcdataResource" et la fonction "ExtraitRcdataResource" sont
    remplacées par une classe "RcdataResource" avec constructeur, destructeur
    et une méthode "Extraction".
  * Ceci est exploité notamment dans "cree_fichier_scan", permettant de ne plus
    avoir de "goto" dans cette fonction.
  * Correction de bug : dans la fonction "lit_chaines", suppression du "ZeroMemory"
    sur l'objet "canal" (cet objet était déjà initialisée par constructeur,
    avec des valeurs pas toutes égales à zéro, et le "ZeroMemory" écrasait ces
    valeurs, avec pour effet indirect de générer de nombreuses réécritures
    inutiles du fichier "chaines.xml").

  recprog.cpp :
  * Correction de bug dans "getDlgProgName" : en raison de l'oubli que les
    caractères en C sont signés par défaut, les codes ASCII supérieurs
    à 0x80 étaient éliminés à la fin des noms de programmations s'ils
    tombaient à la fin.

  Exploitation de ces nouvelles fonctions et macros à de nombreux endroits du
  code (parfois juste pour en améliorer la lisibilité, et aussi, dans le cas des
  strlen_T, pour tirer parti du fait que ces fonctions retournent une valeur
  UINT plutôt que size_t et donc éviter des "casts" de type).

  À plusieurs endroits du code, remplacement de types "size_t" par UINT,
  essentiellement pour éviter des avertissements de compilation en
  configuration x64.

  À plusieurs endroits du code, ajout du déclarateur "static" à des fonctions
  utilisées seulement localement dans le même fichier source.

  Un peu plus de commentaires de documentation, comme d'habitude ...

===================================================================
Old log:
  Finalisation des transformations de compatibilité TCHAR :
  * À peu près toutes les corrections possibles sont faites et vérifiées.
  * Le projet peut maintenant se compiler indifféremment en mode 8 bits et
    Unicode et s'exécuter correctement dans les deux modes.
  * Noter que j'ai fini par trouver un aménagement qui permet de stocker
    la plupart des noms de filtres dans des chaînes TCHAR. Il reste cependant
    quelques exceptions, signalées en commentaires.

  Pouchin TV.sln, Pouchin TV.vcproj :
  * Ajout des configurations Debug_SBCS et Release_SBCS (SBCS = Single Byte
    Character Set) permettant de compiler le projet avec des caractères
    simple octet.
  * Ces configurations se connectent au projet "BaseClasses" en mode
    Debug_MBCS ou Release_MBCS, ce qui en la circonstance ne devrait pas
    poser de problèmes.
  * Ces configurations se connectent au projet "tinyxml" en mode Debug ou
    Release (sachant que dans ce projet, ces modes correspondent
    actuellement au mode SBCS, et que la configuration Unicode devait
    déjà s'y adapter).

  graph.cpp :
  * Ajout des fonctions d'assistance "AddFilterToGraph" pour gérer les ajouts
    de filtres et ne plus dépendre du type de caractères utilisé pour les
    noms de filtres.

  utils.h, utils.cpp :
  * Ajout des fonctions utilitaires "strlen_T" et "strcat_T', qui se joignent aux
    fonctions "strcpy_T" précédemment ajoutées, pour un usage analogue.
  * Ajout d'un typedef "tstring" pour introduire l'utilisation à venir de
    chaînes de caractères "string" ou "wstring" de la bibliothèques STL,
    lesquelles dans de nombreux cas gagneraient à être utilisées plutôt que de
    faire des allocations "malloc/free" ou "new/delete" pour des chaînes de
    caractères (note : limiter quand même l'usage de ceci aux cas où c'est
    nécessaire).
  * Ajout d'une macro STK_ALLOC (exploitant la fonction système "_alloca") pour
    allouer des tableaux de taille dynamiquement calculée, à utiliser pour les
    allocations de mémoire raisonnablement petites et dont la durée de vie est
    limitée à un corps de fonction.
  * Ajout d'une macro COPY_STR_ON_STACK (exploitant STK_ALLOC) pour effectuer
    des copies de chaînes de caractères (avec transformation de largeur de
    caractères éventuelle) dont la durée de vie est limitée à un corps de fonction.
  * Quelques réorganisations dans les fonctions "ConvertUTF82Char", notamment
    en raison du fait qu'en configuration SBCS, l'une d'entre elle venait à
    s'appeler elle-même, amenant un plantage pour cause de débordement de pile.

  ini.h, ini.cpp :
  * Réactivation de la sauvegarde des informations de pistes audio et vidéo (à
    cause des problèmes posés avec les enregistrements programmés). On peut
    cependant continuer à tester en mettant à zéro la macro STREAMS_SAVE_ALL.
  * La structure "RcdataResource" et la fonction "ExtraitRcdataResource" sont
    remplacées par une classe "RcdataResource" avec constructeur, destructeur
    et une méthode "Extraction".
  * Ceci est exploité notamment dans "cree_fichier_scan", permettant de ne plus
    avoir de "goto" dans cette fonction.
  * Correction de bug : dans la fonction "lit_chaines", suppression du "ZeroMemory"
    sur l'objet "canal" (cet objet était déjà initialisée par constructeur,
    avec des valeurs pas toutes égales à zéro, et le "ZeroMemory" écrasait ces
    valeurs, avec pour effet indirect de générer de nombreuses réécritures
    inutiles du fichier "chaines.xml").

  Exploitation de ces nouvelles fonctions et macros à de nombreux endroits du
  code (parfois juste pour en améliorer la lisibilité, et aussi, dans le cas des
  strlen_T, pour tirer parti du fait que ces fonctions retournent une valeur
  UINT plutôt que size_t et donc éviter des "casts" de type).

  À plusieurs endroits du code, remplacement de types "size_t" par UINT,
  essentiellement pour éviter des avertissements de compilation en
  configuration x64.

  À plusieurs endroits du code, ajout du déclarateur "static" à des fonctions
  utilisées seulement localement dans le même fichier source.

  Un peu plus de commentaires de documentation, comme d'habitude ...

From pouchintv-dev at baysse.fr  Sat Jan 10 18:17:13 2009
From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=)
Date: Sat, 10 Jan 2009 18:17:13 +0100 (CET)
Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r163 - log changed
Message-ID: <20090110171713.21CC65F424@mail.baysse.fr>

Author: gingko
Date: 2009-01-10 17:58:21 +0100 (sam, 10 jan 2009)
Revision: 163 - Log changed 

New log:
  Finalisation des transformations de compatibilité TCHAR :
  * À peu près toutes les corrections possibles sont faites et vérifiées.
  * Le projet peut maintenant se compiler indifféremment en mode 8 bits et
    Unicode et s'exécuter correctement dans les deux modes.
  * Noter que j'ai fini par trouver un aménagement qui permet de stocker
    la plupart des noms de filtres dans des chaînes TCHAR. Il reste cependant
    quelques exceptions, signalées en commentaires.

  Pouchin TV.sln, Pouchin TV.vcproj :
  * Ajout des configurations Debug_SBCS et Release_SBCS (SBCS = Single Byte
    Character Set) permettant de compiler le projet avec des caractères
    simple octet.
  * Ces configurations se connectent au projet "BaseClasses" en mode
    Debug_MBCS ou Release_MBCS, ce qui en la circonstance ne devrait pas
    poser de problèmes.
  * Ces configurations se connectent au projet "tinyxml" en mode Debug ou
    Release (sachant que dans ce projet, ces modes correspondent
    actuellement au mode SBCS, et que la configuration Unicode devait
    déjà s'y adapter).

  graph.cpp :
  * Ajout des fonctions d'assistance "AddFilterToGraph" pour gérer les ajouts
    de filtres et ne plus dépendre du type de caractères utilisé pour les
    noms de filtres.

  utils.h, utils.cpp :
  * Ajout des fonctions utilitaires "strlen_T" et "strcat_T', qui se joignent aux
    fonctions "strcpy_T" précédemment ajoutées, pour un usage analogue.
  * Ajout d'un typedef "tstring" pour introduire l'utilisation à venir de
    chaînes de caractères "string" ou "wstring" de la bibliothèques STL,
    lesquelles dans de nombreux cas gagneraient à être utilisées plutôt que de
    faire des allocations "malloc/free" ou "new/delete" pour des chaînes de
    caractères (note : limiter quand même l'usage de ceci aux cas où c'est
    nécessaire).
  * Ajout d'une macro STK_ALLOC (exploitant la fonction système "_alloca") pour
    allouer des tableaux de taille dynamiquement calculée, à utiliser pour les
    allocations de mémoire raisonnablement petites et dont la durée de vie est
    limitée à un corps de fonction.
  * Ajout d'une macro COPY_STR_ON_STACK (exploitant STK_ALLOC) pour effectuer
    des copies de chaînes de caractères (avec transformation de largeur de
    caractères éventuelle) dont la durée de vie est limitée à un corps de fonction.
  * Quelques réorganisations dans les fonctions "ConvertUTF82Char", notamment
    en raison du fait qu'en configuration SBCS, l'une d'entre elle venait à
    s'appeler elle-même, amenant un plantage pour cause de débordement de pile.

  ini.h, ini.cpp :
  * Réactivation de la sauvegarde des informations de pistes audio et vidéo (à
    cause des problèmes posés avec les enregistrements programmés). On peut
    cependant continuer à tester en mettant à zéro la macro STREAMS_SAVE_ALL.
  * La structure "RcdataResource" et la fonction "ExtraitRcdataResource" sont
    remplacées par une classe "RcdataResource" avec constructeur, destructeur
    et une méthode "Extraction".
  * Ceci est exploité notamment dans "cree_fichier_scan", permettant de ne plus
    avoir de "goto" dans cette fonction.
  * Correction de bug : dans la fonction "lit_chaines", suppression du "ZeroMemory"
    sur l'objet "canal" (cet objet était déjà initialisée par constructeur,
    avec des valeurs pas toutes égales à zéro, et le "ZeroMemory" écrasait ces
    valeurs, avec pour effet indirect de générer de nombreuses réécritures
    inutiles du fichier "chaines.xml").

  recprog.cpp :
  * Correction de bug dans "getDlgProgName" : en raison de l'oubli que les
    caractères en C sont signés par défaut, les codes ASCII supérieurs
    à 0x80 étaient éliminés à la fin des noms de programmations s'ils
    tombaient à la fin.

  Exploitation de ces nouvelles fonctions et macros à de nombreux endroits du
  code (parfois juste pour en améliorer la lisibilité, et aussi, dans le cas des
  strlen_T, pour tirer parti du fait que ces fonctions retournent une valeur
  UINT plutôt que size_t et donc éviter des "casts" de type).

  À plusieurs endroits du code, remplacement de types "size_t" par UINT,
  essentiellement pour éviter des avertissements de compilation en
  configuration x64.

  À plusieurs endroits du code, ajout du déclarateur "static" à des fonctions
  utilisées seulement localement dans le même fichier source.

  Un peu plus de commentaires de documentation, comme d'habitude ...

===================================================================
Old log:
  Finalisation des transformations de compatibilité TCHAR :
  * À peu près toutes les corrections possibles sont faites et vérifiées.
  * Le projet peut maintenant se compiler indifféremment en mode 8 bits et
    Unicode et s'exécuter correctement dans les deux modes.
  * Noter que j'ai fini par trouver un aménagement qui permet de stocker
    la plupart des noms de filtres dans des chaînes TCHAR. Il reste cependant
    quelques exceptions, signalées en commentaires.

  Pouchin TV.sln, Pouchin TV.vcproj :
  * Ajout des configurations Debug_SBCS et Release_SBCS (SBCS = Single Byte
    Character Set) permettant de compiler le projet avec des caractères
    simple octet.
  * Ces configurations se connectent au projet "BaseClasses" en mode
    Debug_MBCS ou Release_MBCS, ce qui en la circonstance ne devrait pas
    poser de problèmes.
  * Ces configurations se connectent au projet "tinyxml" en mode Debug ou
    Release (sachant que dans ce projet, ces modes correspondent
    actuellement au mode SBCS, et que la configuration Unicode devait
    déjà s'y adapter).

  graph.cpp :
  * Ajout des fonctions d'assistance "AddFilterToGraph" pour gérer les ajouts
    de filtres et ne plus dépendre du type de caractères utilisé pour les
    noms de filtres.

  utils.h, utils.cpp :
  * Ajout des fonctions utilitaires "strlen_T" et "strcat_T', qui se joignent aux
    fonctions "strcpy_T" précédemment ajoutées, pour un usage analogue.
  * Ajout d'un typedef "tstring" pour introduire l'utilisation à venir de
    chaînes de caractères "string" ou "wstring" de la bibliothèques STL,
    lesquelles dans de nombreux cas gagneraient à être utilisées plutôt que de
    faire des allocations "malloc/free" ou "new/delete" pour des chaînes de
    caractères (note : limiter quand même l'usage de ceci aux cas où c'est
    nécessaire).
  * Ajout d'une macro STK_ALLOC (exploitant la fonction système "_alloca") pour
    allouer des tableaux de taille dynamiquement calculée, à utiliser pour les
    allocations de mémoire raisonnablement petites et dont la durée de vie est
    limitée à un corps de fonction.
  * Ajout d'une macro COPY_STR_ON_STACK (exploitant STK_ALLOC) pour effectuer
    des copies de chaînes de caractères (avec transformation de largeur de
    caractères éventuelle) dont la durée de vie est limitée à un corps de fonction.
  * Quelques réorganisations dans les fonctions "ConvertUTF82Char", notamment
    en raison du fait qu'en configuration SBCS, l'une d'entre elle venait à
    s'appeler elle-même, amenant un plantage pour cause de débordement de pile.

  ini.h, ini.cpp :
  * Réactivation de la sauvegarde des informations de pistes audio et vidéo (à
    cause des problèmes posés avec les enregistrements programmés). On peut
    cependant continuer à tester en mettant à zéro la macro STREAMS_SAVE_ALL.
  * La structure "RcdataResource" et la fonction "ExtraitRcdataResource" sont
    remplacées par une classe "RcdataResource" avec constructeur, destructeur
    et une méthode "Extraction".
  * Ceci est exploité notamment dans "cree_fichier_scan", permettant de ne plus
    avoir de "goto" dans cette fonction.
  * Correction de bug : dans la fonction "lit_chaines", suppression du "ZeroMemory"
    sur l'objet "canal" (cet objet était déjà initialisée par constructeur,
    avec des valeurs pas toutes égales à zéro, et le "ZeroMemory" écrasait ces
    valeurs, avec pour effet indirect de générer de nombreuses réécritures
    inutiles du fichier "chaines.xml").

  recprog.cpp :
  * Correction de bug dans "getDlgProgName" : en raison de l'oubli que les
    caractères en C sont signés par défaut, les codes ASCII supérieurs
    à 0x80 étaient éliminés à la fin des noms de programmations s'ils
    tombaient à la fin.

  Exploitation de ces nouvelles fonctions et macros à de nombreux endroits du
  code (parfois juste pour en améliorer la lisibilité, et aussi, dans le cas des
  strlen_T, pour tirer parti du fait que ces fonctions retournent une valeur
  UINT plutôt que size_t et donc éviter des "casts" de type).

  À plusieurs endroits du code, remplacement de types "size_t" par UINT,
  essentiellement pour éviter des avertissements de compilation en
  configuration x64.

  À plusieurs endroits du code, ajout du déclarateur "static" à des fonctions
  utilisées seulement localement dans le même fichier source.

  Un peu plus de commentaires de documentation, comme d'habitude ...

From pouchintv-dev at baysse.fr  Fri Jan 16 16:25:32 2009
From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=)
Date: Fri, 16 Jan 2009 16:25:32 +0100 (CET)
Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r166 - trunk
Message-ID: <20090116152532.BF5E35F3F4@mail.baysse.fr>

Author: gingko
Date: 2009-01-16 16:25:32 +0100 (ven, 16 jan 2009)
New Revision: 166

Modified:
   trunk/ini.cpp
   trunk/ini.h
   trunk/main.cpp
   trunk/rendering.cpp
   trunk/rendering.h
   trunk/res.rc
   trunk/resource.h
   trunk/settings.cpp
Log:
Ajout des modes d'affichage "VMR7 windowless" et "Aucun rendu vidéo".

  rendering.h, rendering.cpp, main.cpp :
  * Ajout d'un mode "VMR7 windowless" (d'après le patch proposé par MatMaul dans le
    forum), mais sans pour autant supprimer le mode "VMR7 renderless" existant.
  * Ajout d'un mode "Aucun rendu vidéo", dans lequel aucun affichage vidéo n'est
    produit. Il reste cependant possible d'y effectuer des enregistrements.
    Ceci peut être utile, par exemple, si on veut enregistrer des programmes sur un
    ordinateur qui n'a pas le support matériel suffisant pour afficher la vidéo
    correctement (certaines machines virtuelles, ou bien d'anciens ordinateurs
    portables, par exemple).
    Les personnes qui se servent de VLC pour regarder des programmes en
    "timeshifting" improvisé pourront aussi y trouver un intérêt.
    À noter que dans ce mode, l'écran est barré d'une grande croix bleue, afin de
    le distinguer, par exemple, d'une panne d'affichage. L'OSD reste opérationnel.

  ini.h, ini.cpp, settings.cpp, resource.h, res.rc :
  * Modification du dialogue de configuration des options, afin de prendre en charge
    les deux nouveaux modes d'affichage.


Modifié: trunk/ini.cpp
===================================================================
--- trunk/ini.cpp	2009-01-11 19:56:21 UTC (rev 165)
+++ trunk/ini.cpp	2009-01-16 15:25:32 UTC (rev 166)
@@ -299,7 +299,8 @@
  **/
 AssocElement aVMRModeTable[] =
 {
-	{TEXT("VMR7 windowless"),	vmt_VMR7_windowless},	// (en attente d'implémentation)
+	{TEXT("Aucun"),				vmt_null},
+	{TEXT("VMR7 windowless"),	vmt_VMR7_windowless},
 	{TEXT("VMR7 renderless"),	vmt_VMR7_renderless},
 	{TEXT("VMR9 windowless"),	vmt_VMR9_windowless},
 	{TEXT("VMR9 renderless"),	vmt_VMR9_renderless},	// (en attente d'implémentation)

Modifié: trunk/ini.h
===================================================================
--- trunk/ini.h	2009-01-11 19:56:21 UTC (rev 165)
+++ trunk/ini.h	2009-01-16 15:25:32 UTC (rev 166)
@@ -56,8 +56,8 @@
  * Listes des types de VMR disponibles
  **/
 enum VMRTypes {
-	vmt_null,	//!< Aucun VMR défini
-	vmt_VMR7_windowless,	//!< \todo VMR version 7 windowless (en attente d'implémentation)
+	vmt_null,				//!< Aucun VMR défini
+	vmt_VMR7_windowless,	//!< VMR version 7 windowless
 	vmt_VMR7_renderless,	//!< VMR version 7 renderless
 	vmt_VMR9_windowless,	//!< VMR version 9 windowless
 	vmt_VMR9_renderless		//!< \todo VMR version 9 renderless (en attente d'implémentation)

Modifié: trunk/main.cpp
===================================================================
--- trunk/main.cpp	2009-01-11 19:56:21 UTC (rev 165)
+++ trunk/main.cpp	2009-01-16 15:25:32 UTC (rev 166)
@@ -1823,14 +1823,10 @@
 			update_status_size();
 		}
 		update_coords();
+		if (pVMR)
+			pVMR->Resize();
 		break;
 
-	/* (probablement pas utile)
-	case WM_MOVE:
-		update_coords();
-		break;
-	*/
-
 	case WM_CLOSE:
 		//if (IsMinimized(hWnd))
 		//	ShowWindow(hWnd, SW_RESTORE);
@@ -2447,7 +2443,7 @@
 			is_vista = true;
 
 			// Sous Vista, on n'utilise l'OSD qu'avec le VMR9
-			if (vmr_mode==vmt_VMR7_renderless)
+			if (vmr_mode==vmt_VMR7_renderless || vmr_mode==vmt_VMR7_windowless)
 				use_osd = false;
 
 			myprintf(TEXT("Fonctionne sous Vista ou 2008 Serveur ou plus récent\t"));

Modifié: trunk/rendering.cpp
===================================================================
--- trunk/rendering.cpp	2009-01-11 19:56:21 UTC (rev 165)
+++ trunk/rendering.cpp	2009-01-16 15:25:32 UTC (rev 166)
@@ -204,12 +204,12 @@
 	SetTextColor(hDC, OSD_COLOR);
 
 	// Couleur de fond (remplacée par de la transparence)
-    SetBkColor(hDC, colorKey);
+	SetBkColor(hDC, colorKey);
 
 	SetTextAlign(hDC, sRefs.bRJustif ? TA_RIGHT : TA_LEFT);
 	ExtTextOut(hDC, sRefs.bRJustif ? sRefs.right : sRefs.left, sRefs.top,
 		ETO_CLIPPED|ETO_OPAQUE, &sRefs, sRefs.pszText, bHidden ? 0 : sRefs.nTxtSize, NULL);
-    SelectObject(hDC, hOldFont);
+	SelectObject(hDC, hOldFont);
 }
 
 // ====================================================================================
@@ -417,7 +417,7 @@
 /// (normalement appelé en réponse à \p WM_PAINT)
 /// \param[in] hDC Handle sur "display context" à utiliser
 void COsdAllObjects::DoPaint(HDC hDC)
- {
+{
 	cTopRight.Paint(hDC);
 	cTopRight2.Paint(hDC);
 	cBotRight.Paint(hDC);
@@ -569,18 +569,65 @@
 	return ar;
 }
 
+void CVideoMixingRenderer::DrawOsdText(COsdObject & cOsdObj, bool bHidden)
+{
+	// Par défaut, on ne dessine pas d'objet. En lieu et place, on demande à l'objet appelant
+	// d'invalider son rectangle, de façon à ce que le prochain appel à WM_PAINT provoque
+	// cet affichage en mode "device context".
+	cOsdObj.DoInvalidate();
+}
+
+void CVideoMixingRenderer::Paint(HDC hDC)
+{
+	if (pOSD)
+		pOSD->DoPaint(hDC);
+}
+
 // ====================================================================================
+// Déclaration de la classe CNullVideoRenderer
+// ====================================================================================
+
+/// Classe de substitution pour l'absence de rendu vidéo
+class CNullVideoRenderer : public CVideoMixingRenderer
+{
+	HPEN hPen;
+
+	/// Création et ajout du filtre
+	virtual HRESULT	CreateAndAdd();
+
+	/// Point d'appel pour redessiner cet objet OSD en réponse à \p WM_PAINT
+	/// \param[in]	hDC	"Device context" à utiliser
+	virtual void	Paint(HDC hDC);
+
+	/// Appel sur notification de redimensionnement de la fenêtre
+	virtual void	Resize() {
+						InvalidateRect(hMainWnd, NULL, TRUE);}
+
+	/// Invalidation du rectangle d'un objets OSD, afin de provoquer son réaffichage
+	/// (appel délégué depuis \p COsdObject)
+	/// \param[in]	cOsdObj	(ici inutilisé)
+	virtual void	Invalidate(COsdObject & cOsdObj) {
+						// On invalide ici toute la fenêtre.
+						InvalidateRect(hMainWnd, NULL, TRUE);	}
+
+public:
+	/// Constructeur
+	CNullVideoRenderer();
+
+	/// Destructeur
+	virtual ~CNullVideoRenderer();
+};
+
+// ====================================================================================
 // Déclaration de la classe CVideoMixingRenderer7
 // ====================================================================================
 
-/// Implémentation utilisant le Video Mixing Renderer version 7
+/// Classe commune pour les implémentations utilisant le Video Mixing Renderer version 7
 class CVideoMixingRenderer7 : public CVideoMixingRenderer
 {
 	CComPtr pVMR7Control;
 
 	virtual HRESULT		CreateAndAdd();
-	virtual HRESULT		Configure();
-	virtual HRESULT		PrepareSurface();
 	virtual HRESULT		InitDeinterlace();	//!< \todo Voir \p CVideoMixingRenderer::InitDeinterlace
 	virtual HRESULT		InitControl();
 
@@ -616,11 +663,6 @@
 	/// \return				Rectangle calculé, utilisable pour l'OSD
 	virtual RECT		CalcOsdRect(RECT sRect);
 
-	/// Affichage d'un texte OSD
-	/// \param[in]	cOsdObj	Référence sur l'objet à afficher
-	/// \param[in]	bHidden	Texte invisible si \p true (ne dessiner que le fond)
-	virtual void		DrawOsdText(COsdObject & cOsdObj, bool bHidden);
-
 	/// Invalidation du rectangle d'un objets OSD, afin de provoquer son réaffichage
 	/// (appel délégué depuis \p COsdObject)
 	/// \param[in]	cOsdObj	Référence sur l'objet à invalider
@@ -631,12 +673,40 @@
 
 	/// Effacement de tout le contenu OSD couramment affiché
 	virtual void		ClearOsd();
+};
 
-	/// Redessiner l'espace de la vidéo
-	virtual void		Paint(HDC hDC);
+// ====================================================================================
+// Déclaration de la classe CVideoMixingRenderer7_renderless
+// ====================================================================================
+
+/// Implémentation utilisant le Video Mixing Renderer version 7 en mode "renderless"
+class CVideoMixingRenderer7_renderless : public CVideoMixingRenderer7
+{
+	virtual HRESULT		Configure();
+	virtual HRESULT		PrepareSurface();
+public:
+	// Constructeur
+	CVideoMixingRenderer7_renderless() :
+		CVideoMixingRenderer7()
+	{}
 };
 
 // ====================================================================================
+// Déclaration de la classe CVideoMixingRenderer7_windowless
+// ====================================================================================
+
+/// Implémentation utilisant le Video Mixing Renderer version 7 en mode "windowless"
+class CVideoMixingRenderer7_windowless : public CVideoMixingRenderer7
+{
+	virtual HRESULT		Configure();
+public:
+	// Constructeur
+	CVideoMixingRenderer7_windowless() :
+		CVideoMixingRenderer7()
+	{}
+};
+
+// ====================================================================================
 // Déclaration de la classe CVideoMixingRenderer9
 // ====================================================================================
 
@@ -657,10 +727,10 @@
 	/// Calcul de la taille à attribuer au bitmap à incruster dans la vidéo
 	SIZE				GetBitmapSize();
 
-    /// Vérification avec remplacement éventuel du bitmap à associer à l'affichage,
+	/// Vérification avec remplacement éventuel du bitmap à associer à l'affichage,
 	/// et récupération du "device context" qui s'y associe.
 	/// \param[in]	sNewBMSiz	dimensions du bitmap qui sera créé s'il n'existe pas; s'il
-	///                         en existe un qui n'a pas ces dimensions, un nouveau sera créé
+	///							en existe un qui n'a pas ces dimensions, un nouveau sera créé
 	///							et l'ancien sera détruit.
 	/// \return		"Device context" du bitmap créé ou préexistant
 	HDC					GetBitmapDC(SIZE sNewBMSiz);
@@ -679,7 +749,7 @@
 		return bEtirer ? VMR9ARMode_None : VMR9ARMode_LetterBox;}
 public:
 	CVideoMixingRenderer9() :
-	  dwLastOsdSet(0)
+		dwLastOsdSet(0)
 	{
 		/*sOsdRect.top = sOsdRect.left = 0.0;
 		sOsdRect.bottom = sOsdRect.right = 1.0f;*/
@@ -724,6 +794,59 @@
 };
 
 // ====================================================================================
+// Implémentations des méthodes de la classe CNullVideoRenderer
+// ====================================================================================
+
+/// Constructeur
+CNullVideoRenderer::CNullVideoRenderer() :
+	CVideoMixingRenderer(),
+	hPen(NULL)
+{
+	LOGBRUSH sLbrsh = {
+		BS_SOLID,
+		RGB(0, 0, 192),	// bleu pas trop intense
+		0
+	};
+
+	hPen = ExtCreatePen(PS_COSMETIC|PS_SOLID, 1, &sLbrsh, 0, NULL);
+}
+
+/// Création et ajout du filtre
+HRESULT CNullVideoRenderer::CreateAndAdd()
+{
+	return
+		create_and_add_filter(
+			CLSID_NullRenderer, TEXT("Null Renderer"), *this);
+}
+
+/// Point d'appel pour redessiner cet objet OSD en réponse à \p WM_PAINT
+/// \param[in]	hDC	"Device context" à utiliser
+/// \todo Ajouter éventuellement un texte "Sortie vidéo désactivée" en milieu d'affichage
+void CNullVideoRenderer::Paint(HDC hDC)
+{
+
+	__super::Paint(hDC);	// Gérer l'OSD standard
+
+	RECT	sRect = CalcCliRect();
+
+	// Dessiner une croix en travers de l'affichage
+	HPEN hPenSav = (HPEN)SelectObject(hDC, hPen);
+
+	MoveToEx(hDC, sRect.left, sRect.top, NULL);
+	LineTo(hDC, sRect.right, sRect.bottom);
+	MoveToEx(hDC, sRect.left, sRect.bottom, NULL);
+	LineTo(hDC, sRect.right, sRect.top);
+	SelectObject(hDC, hPenSav);
+}
+
+/// Destructeur
+CNullVideoRenderer::~CNullVideoRenderer()
+{
+	if (hPen)
+		DeleteObject(hPen);
+}
+
+// ====================================================================================
 // Implémentations des méthodes de la classe CVideoMixingRenderer7
 // ====================================================================================
 
@@ -792,64 +915,6 @@
 			CLSID_VideoMixingRenderer, TEXT("Video Mixing Renderer"), *this);
 }
 
-HRESULT CVideoMixingRenderer7::Configure()
-{
-	CComQIPtr pVMRConfig(*this);
-
-	if (!pVMRConfig)
-		return erreur(
-			TEXT("L'interface de configuration VMR n'est pas disponible"),
-			E_NOINTERFACE);
-
-	HRESULT hr = pVMRConfig->SetRenderingMode(VMRMode_Renderless);
-
-	if (SUCCEEDED(hr) && use_vmr_deinterlace)
-		hr = pVMRConfig->SetNumberOfStreams(1);
-	return hr;
-}
-
-HRESULT CVideoMixingRenderer7::PrepareSurface()
-{
-	CComQIPtr pNotify(*this);
-
-	if (!pNotify)
-		return erreur(
-			TEXT("L'interface IVMRSurfaceAllocatorNotify n'a pas été trouvée"),
-			E_NOINTERFACE);
-
-	CComPtr pSurfAlloc;
-
-	HRESULT hr = pSurfAlloc.CoCreateInstance(CLSID_AllocPresenter, NULL, CLSCTX_INPROC_SERVER);
-
-	if (FAILED(hr))
-		return erreur(TEXT("L'interface IVMRSurfaceAllocator n'a pas été trouvée"), hr);
-
-	{
-		CComQIPtr pPresConf(pSurfAlloc);
-
-		if (!pPresConf)
-			return erreur(
-				TEXT("L'interface IVMRImagePresenterConfig n'a pas été trouvée"),
-				E_NOINTERFACE);
-
-		hr = pPresConf->SetRenderingPrefs(
-				is_vista ?
-				RenderPrefs_AllowOffscreen :
-				(RenderPrefs_ForceOverlays | RenderPrefs_DoNotRenderColorKeyAndBorder)
-			);
-
-		if (FAILED(hr))
-			return erreur(TEXT("Échec de SetRenderingPrefs"), hr);
-	}
-
-	hr = pNotify->AdviseSurfaceAllocator(0x118218, pSurfAlloc);
-	myprintf(TEXT("%?erreur AdviseSurfaceAllocator, hr=0x%08x\n"), FAILED(hr), hr);
-	hr = pSurfAlloc->AdviseNotify(pNotify);
-	myprintf(TEXT("%?erreur AdviseNotify, hr=0x%08x\n"), FAILED(hr), hr);
-
-	return hr;
-}
-
 HRESULT CVideoMixingRenderer7::InitControl()
 {
 	HRESULT hr = QueryInterface(&pVMR7Control);
@@ -918,19 +983,13 @@
 	return E_FAIL;
 }
 
-void CVideoMixingRenderer7::Paint(HDC hDC)
-{
-	if (pOSD)
-		pOSD->DoPaint(hDC);
-}
-
 /// Obtenir la résolution native de la vidéo
 SIZE CVideoMixingRenderer7::GetNativeSize() const
 {
 	SIZE	sSz	= {768, 576};	// valeurs par défaut en cas d'erreur
 	HRESULT hr	= pVMR7Control->GetNativeVideoSize(&sSz.cx, &sSz.cy, NULL, NULL);
 
-    myprintf(TEXT("%?GetNativeVideoSize FAILED!, hr=0x%08x\n"), FAILED(hr), hr);
+	myprintf(TEXT("%?GetNativeVideoSize FAILED!, hr=0x%08x\n"), FAILED(hr), hr);
 
 	return sSz;
 }
@@ -944,19 +1003,100 @@
 	return sRect;
 }
 
-void CVideoMixingRenderer7::DrawOsdText(COsdObject & cOsdObj, bool bHidden)
+void CVideoMixingRenderer7::ClearOsd()
 {
-	// Le VMR7 ne dessine pas d'objet lui-même. En lieu et place, on demande à l'objet appelant
-	// d'invalider son rectangle, de façon à ce que le prochain appel à WM_PAINT provoque
-	// cet affichage en mode "device context".
-	cOsdObj.DoInvalidate();
 }
 
-void CVideoMixingRenderer7::ClearOsd()
+// ====================================================================================
+// Implémentations des méthodes de la classe CVideoMixingRenderer7_renderless
+// ====================================================================================
+
+HRESULT CVideoMixingRenderer7_renderless::Configure()
 {
+	CComQIPtr pVMRConfig(*this);
+
+	if (!pVMRConfig)
+		return erreur(
+			TEXT("L'interface de configuration VMR n'est pas disponible"),
+			E_NOINTERFACE);
+
+	HRESULT hr = pVMRConfig->SetRenderingMode(VMRMode_Renderless);
+
+	if (SUCCEEDED(hr) && use_vmr_deinterlace)
+		hr = pVMRConfig->SetNumberOfStreams(1);
+	return hr;
 }
 
+HRESULT CVideoMixingRenderer7_renderless::PrepareSurface()
+{
+	CComQIPtr pNotify(*this);
+
+	if (!pNotify)
+		return erreur(
+			TEXT("L'interface IVMRSurfaceAllocatorNotify n'a pas été trouvée"),
+			E_NOINTERFACE);
+
+	CComPtr pSurfAlloc;
+
+	HRESULT hr = pSurfAlloc.CoCreateInstance(CLSID_AllocPresenter, NULL, CLSCTX_INPROC_SERVER);
+
+	if (FAILED(hr))
+		return erreur(TEXT("L'interface IVMRSurfaceAllocator n'a pas été trouvée"), hr);
+
+	{
+		CComQIPtr pPresConf(pSurfAlloc);
+
+		if (!pPresConf)
+			return erreur(
+				TEXT("L'interface IVMRImagePresenterConfig n'a pas été trouvée"),
+				E_NOINTERFACE);
+
+		hr = pPresConf->SetRenderingPrefs(
+				is_vista ?
+				RenderPrefs_AllowOffscreen :
+				(RenderPrefs_ForceOverlays | RenderPrefs_DoNotRenderColorKeyAndBorder)
+			);
+
+		if (FAILED(hr))
+			return erreur(TEXT("Échec de SetRenderingPrefs"), hr);
+	}
+
+	hr = pNotify->AdviseSurfaceAllocator(0x118218, pSurfAlloc);
+	myprintf(TEXT("%?erreur AdviseSurfaceAllocator, hr=0x%08x\n"), FAILED(hr), hr);
+	hr = pSurfAlloc->AdviseNotify(pNotify);
+	myprintf(TEXT("%?erreur AdviseNotify, hr=0x%08x\n"), FAILED(hr), hr);
+
+	return hr;
+}
+
 // ====================================================================================
+// Implémentations des méthodes de la classe CVideoMixingRenderer7_windowless
+// ====================================================================================
+
+HRESULT CVideoMixingRenderer7_windowless::Configure()
+{
+	CComQIPtr pVMRConfig(*this);
+
+	if (!pVMRConfig)
+		return erreur(
+			TEXT("L'interface de configuration VMR n'est pas disponible"),
+			E_NOINTERFACE);
+
+	HRESULT hr = pVMRConfig->SetRenderingMode(VMRMode_Windowless);
+
+	if (SUCCEEDED(hr)) {
+		hr = pVMRConfig->SetRenderingPrefs(
+			is_vista ?
+			RenderPrefs_AllowOffscreen :
+			(RenderPrefs_ForceOverlays | RenderPrefs_DoNotRenderColorKeyAndBorder)
+		);
+		if (SUCCEEDED(hr) && use_vmr_deinterlace)
+			hr = pVMRConfig->SetNumberOfStreams(1);
+	}
+	return hr;
+}
+
+// ====================================================================================
 // Implémentations des méthodes de la classe CVideoMixingRenderer9
 // ====================================================================================
 
@@ -1145,7 +1285,7 @@
 	SIZE	sSz	= {768, 576};	// valeurs par défaut en cas d'erreur
 	HRESULT hr	= pVMR9Control->GetNativeVideoSize(&sSz.cx, &sSz.cy, NULL, NULL);
 
-    myprintf(TEXT("%?GetNativeVideoSize FAILED!, hr=0x%08x\n"), FAILED(hr), hr);
+	myprintf(TEXT("%?GetNativeVideoSize FAILED!, hr=0x%08x\n"), FAILED(hr), hr);
 
 	return sSz;
 }
@@ -1260,7 +1400,7 @@
 
 	LimitOsdRate();	// Limitations du nombre de changements par seconde
 
-    HRESULT hr = pBMP->SetAlphaBitmap(&bmpInfo);
+	HRESULT hr = pBMP->SetAlphaBitmap(&bmpInfo);
 
 	myprintf(TEXT("%?SetAlphaBitmap FAILED!  hr=0x%x\r\n\r\n%s\n"), FAILED(hr), hr, STR_VMR_DISPLAY_WARNING);
 
@@ -1304,8 +1444,16 @@
 
 		switch (vmr_mode) {
 
+		case vmt_null:
+			pVMR = new CNullVideoRenderer();
+			break;
+
+		case vmt_VMR7_windowless:
+			pVMR = new CVideoMixingRenderer7_windowless();
+			break;
+
 		case vmt_VMR7_renderless:
-			pVMR = new CVideoMixingRenderer7();
+			pVMR = new CVideoMixingRenderer7_renderless();
 			break;
 
 		case vmt_VMR9_windowless:

Modifié: trunk/rendering.h
===================================================================
--- trunk/rendering.h	2009-01-11 19:56:21 UTC (rev 165)
+++ trunk/rendering.h	2009-01-16 15:25:32 UTC (rev 166)
@@ -66,7 +66,8 @@
 	virtual HRESULT		CreateAndAdd() = 0;
 
 	/// Configuration du VMR
-	virtual HRESULT		Configure() = 0;
+	virtual HRESULT		Configure() {
+							return S_OK;}
 
 	/// Préparation de la surface (utile seulement en mode RenderLess) :
 	virtual HRESULT		PrepareSurface() {
@@ -81,7 +82,8 @@
 							return S_OK;}
 
 	/// Initialisation et configuration de l'interface de contrôle
-	virtual HRESULT		InitControl() = 0;
+	virtual HRESULT		InitControl() {
+							return S_OK;};
 
 public:
 	/// Constructeur
@@ -92,40 +94,46 @@
 	/// \note : Ceci fait peut-être double emploi avec la commande incluse
 	/// dans \p SetVideoPosition. Vérifier.
 	/// \param[in]	bEtirer		Déformer la vidéo si nécessaire pour remplir le rectangle
-	virtual HRESULT		SetAspectRatioMode(bool bEtirer=false) = 0;
+	virtual HRESULT		SetAspectRatioMode(bool bEtirer=false) {
+							return S_OK;}
 
 	/// Définition de la position d'affichage et du ratio d'aspect.
 	/// \param[in]	pDstRect	Rectangle de la nouvelle position de l'affichage
 	/// \param[in]	bEtirer		Déformer la vidéo si nécessaire pour remplir le rectangle
-	virtual HRESULT		SetVideoPosition(const LPRECT pDstRect, bool bEtirer) const = 0;
+	virtual HRESULT		SetVideoPosition(const LPRECT pDstRect, bool bEtirer) const {
+							return S_OK;}
 
 	/// Obtenir la résolution native de la vidéo
-	virtual SIZE		GetNativeSize() const = 0;
+	virtual SIZE		GetNativeSize() const  {
+							SIZE sSiz = {0, 0}; return sSiz;}
 
 	/// Signifier au VMR que le mode d'affichage a changé
-	virtual HRESULT		DisplayModeChanged() = 0;
+	virtual HRESULT		DisplayModeChanged() {
+							return S_OK;}
 
 	/// Récupérer l'image affichée (en vue d'une capture statique)
 	/// \param[out]	pDib	Pointeur recevant l'image capturée
-	virtual HRESULT		GetCurrentImage(CComHeapPtr & pDib) = 0;
+	virtual HRESULT		GetCurrentImage(CComHeapPtr & pDib)  {
+							return S_OK;}
 
 	/// Calcul du rectangle utilisé pour la vidéo (à l'usage de la construction de l'OSD)
 	/// \param[in] sRect	Rectangle client de la fenêtre, calculé par \p CalcCliRect
 	/// \return				Rectangle calculé, utilisable pour l'OSD
-	virtual RECT		CalcOsdRect(RECT sRect) = 0;
+	virtual RECT		CalcOsdRect(RECT sRect) {
+							return sRect;};
 
 	/// Affichage d'un texte OSD
 	/// \param[in]	cOsdObj	Référence sur l'objet à afficher
 	/// \param[in]	bHidden	Effacer le rectangle au lieu d'afficher le texte
-	virtual void		DrawOsdText(COsdObject & cOsdObj, bool bHidden) = 0;
+	virtual void		DrawOsdText(COsdObject & cOsdObj, bool bHidden);
 
-	/// Invalidation du rectangle d'un objets OSD, afin de provoquer son réaffichage
+	/// Invalidation du rectangle d'un objet OSD, afin de provoquer son réaffichage
 	/// (appel délégué depuis \p COsdObject)
 	/// \param[in]	cOsdObj	Référence sur l'objet à invalider
-	virtual void		Invalidate(COsdObject & cOsdObj) {}	// pas toujours nécessaire
+	virtual void		Invalidate(COsdObject & cOsdObj) {}
 
 	/// Effacement de tout le contenu OSD couramment affiché
-	virtual void		ClearOsd() = 0;
+	virtual void		ClearOsd() {}
 
 	/// Ouverture du dialogue de propriétés du VMR
 	VOID				create_property_dialog();
@@ -140,8 +148,11 @@
 	HRESULT				Connect(CComPtr & pVidCodec);
 
 	/// Redessiner l'espace de la vidéo
-	virtual void		Paint(HDC hDC) = 0;
+	virtual void		Paint(HDC hDC);
 
+	/// Appel sur notification de redimensionnement de la fenêtre
+	virtual void		Resize() {}
+
 	/// Destructeur
 	virtual ~CVideoMixingRenderer() {}
 };
@@ -154,6 +165,7 @@
 class COsdObject
 {
 	friend class COsdAllObjects;
+	friend class CVideoMixingRenderer;
 	friend class CVideoMixingRenderer7;
 
 	COsdAllObjects	&	cOSD;			//

Author: gingko
Date: 2009-01-17 03:17:13 +0100 (sam, 17 jan 2009)
New Revision: 167

Modified:
   trunk/channels.cpp
   trunk/ini.cpp
   trunk/ini.h
   trunk/main.cpp
   trunk/main.h
   trunk/pmtfilter.cpp
   trunk/recprog.cpp
   trunk/recprog.h
   trunk/rendering.cpp
Log:
Correctifs mineurs, et commentaires.

  recprog.cpp :
  * Réécriture de la récupération du mot de passe pour le planificateur de tâches dans
    "PaswdDialogProc" (ancien code douteux, et bug intermittent (?) signalé par certains
    à ce niveau).
  * Correctif dans la reconduction des enregistrements programmés avec répétition
    (Programme::ajustementDesRepetitions) : la reconduction ne se faisait pas dans le
    cas où une des répétitions était sautée, par exemple parce que l'ordinateur était
    éteint au mauvais moment.
  * "init_programmation" : petit correctif dans le tri des enregistrements programmés
    (ce tri était parfois "oublié").
  * "DelayedStopDialogProc" : les cases à cocher "Fermer Pouchin TV Mod" et "Éteindre
    la lumière en partant" sont maintenant liées entre elles de la même manière que
    dans "RecordDialogProc".
  * Commentaires ajoutés ou réorganisés

  pmtfilter.cpp, main.cpp :
  * En cas de changement du paramétrage d'une chaîne en cours de diffusion, le fichier
    "chaines.xml" était sauvegardé, avec les changements détectés. Cette sauvegarde est
    maintenant déplacée dans "main.cpp", derrière la notification WM_APP_PMT_UPDATED,
    afin de s'assurer qu'elle soit réalisée dans le "thread" principal et non pas dans
    celui du filtre PMT, ce qui est vaguement dangereux (et justement, on a probablement
    un bug intermittent à ce niveau, donc avec un peu de chance ...).

  ini.h, ini.cpp :
  * Déplacement de l'ensemble du groupe des variables de configuration (celles
    dont la valeur est sauvegardée dans "config.ini") dans ce module. La plupart sont
    issues de main.h/main.cpp, quelques unes étaient déjà dans ini.cpp, une vient de
    channels.cpp.

Modifié: trunk/channels.cpp
===================================================================
--- trunk/channels.cpp	2009-01-16 15:25:32 UTC (rev 166)
+++ trunk/channels.cpp	2009-01-17 02:17:13 UTC (rev 167)
@@ -37,7 +37,6 @@
 
 int ixChaineCourante = -1;
 int ixSonCourant = 0;
-long volumeCourant = 0;
 bool suspendu = true;	// 'true' si vidéo et audio suspendus (à l'initialisation, ou si minimisé + 'suspend_minimized')
 
 // Taille des images des chaînes (largeur et longueur)

Modifié: trunk/ini.cpp
===================================================================
--- trunk/ini.cpp	2009-01-16 15:25:32 UTC (rev 166)
+++ trunk/ini.cpp	2009-01-17 02:17:13 UTC (rev 167)
@@ -108,6 +108,46 @@
 TCHAR			prefix_conf[32] = TEXT("");
 
 /**
+ * Variable à mettre à 'true' toutes les fois que quelque chose a été modifié
+ * dans les enregistrements programmés, nécessitant une sauvegarde.
+ **/
+bool			programmation_modifiee = false;
+
+// ====================================================================================
+// Variables de configuration
+// ====================================================================================
+
+TCHAR			filtreMPEG2[256];
+TCHAR			filtreAudio[256];
+TCHAR			filtreAc3[256];
+TCHAR			nomVille[256];
+bool			exact_match;
+
+TCHAR			nom_tuner[256];
+TCHAR			nom_receiver[256];
+
+TCHAR			screenshots_dir[MAX_PATH];
+TCHAR			video_dir[MAX_PATH];
+
+int				avance_enreg;
+int				retard_enreg;
+int				offset_tuner;
+bool			suspend_minimized		= false;
+bool			minimize_system_tray	= false;
+bool			use_vmr_deinterlace		= false;
+bool			allow_stream_record		= false;
+
+bool			use_msn					= false;
+bool			on_top					= false;
+bool			use_ac3					= false;
+bool			use_osd					= true;
+VMRTypes		vmr_mode;
+
+PanModes		video_pan_mode			= pm_Normal;
+int				zoom_ratio				= 100;
+long			volumeCourant			= 0;
+
+/**
  * Motif pour le nom des fichiers pour les enregistrements, ainsi que la valeur par défaut
  
  *    %c = chaîne
@@ -119,26 +159,15 @@
  *    %h = heure
  *    %M = minute
  *    %s = secondes
- * \todo Déplacer dans le groupe \p configVars, avec les autres variables de configuration. **/ -TCHAR motif_noms_enreg[MAX_PATH]; +TCHAR motif_noms_enreg[MAX_PATH]; -/** - * Variable à mettre à 'true' toutes les fois que quelque chose a été modifié - * dans les enregistrements programmés, nécessitant une sauvegarde. - **/ -bool programmation_modifiee = false; +int epg_typerecvideo; //!< Type d'enregistrement précédement utilisé dans la + //!< fenêtre EPG pour la vidéo +int epg_typerecaudio; //!< Type d'enregistrement précédement utilisé dans la + //!< fenêtre EPG pour l'audio -/** - * Type d'enregistrement précédement utilisé dans la fenêtre epg pour la vidéo - **/ -int epg_typerecvideo; -/** - * Type d'enregistrement précédement utilisé dans la fenêtre epg pour l'audio - **/ -int epg_typerecaudio; - // ==================================================================================== // Variables locales // ==================================================================================== @@ -692,6 +721,10 @@ /** * Lecture des programmations d'enregistrement depuis un fichier. + * \todo Retirer dans quelques versions (car plus utile) l'ancien système de sauvegarde des + * enregistrements programmés, exploitant les tableaux \p Xstn_S et \p Xstn_E, ainsi que le + * recalcul du SID avec \p indexToSID ; attention cependant aux personnes qui migreraient + * tardivement depuis une très ancienne version du programme. **/ int lit_programmes(void) { @@ -706,7 +739,6 @@ TEXT("Seconde") }; - /// \todo à retirer dans quelques versions (car plus utile) // Anciens noms de début d'enregistrement static const XMLSystemTimeNames Xstn_S = { TEXT("S_Annee"), @@ -718,7 +750,6 @@ TEXT("S_Seconde") }; - /// \todo à retirer dans quelques versions (car plus utile) // Anciens noms de fin d'enregistrement static const XMLSystemTimeNames Xstn_E = { TEXT("E_Annee"), @@ -759,7 +790,6 @@ prog.methode = (MethodeEnregistrement)pNode->getInt(TEXT("Methode")); prog.audio = (AudioMode)pNode->getInt(TEXT("Audio")); - /// \todo à retirer dans quelques versions (car plus utile) // Ajustement de compatibilité permettant de récupérer correctement les programmations // faites avec les anciennes versions qui ne sauvegardaient pas le SID. if (prog.sidChaine==0) @@ -775,7 +805,6 @@ delete enregistrements; enregistrements = NULL; } else { - /// \todo à retirer dans quelques versions (car plus utile) // Ancien style xmlLoadSystemTime(pNode, prog.debut, Xstn_S); } Modifié: trunk/ini.h =================================================================== --- trunk/ini.h 2009-01-16 15:25:32 UTC (rev 166) +++ trunk/ini.h 2009-01-17 02:17:13 UTC (rev 167) @@ -83,6 +83,66 @@ etf_minimized ///< minimisée (en icône ou pas) }; +// ==================================================================================== +// Variables de configuration +// ==================================================================================== + +/** @defgroup configVars Variables de configuration + * Ces variables contiennent les données qui sont sauvegardées entre les sessions \p PouchinTVMod. + * elles sont chargées au démarrage de l'application, et sont sauvegardées chaque fois qu'une + * modification intervient dans l'une de celles-ci. + * \todo Autres éléments de configuration à prévoir : + * - Voir #OSD_COLOR, #OSD_TRANSPARENCY. + * @{ + **/ + +extern TCHAR filtreMPEG2[256]; //!< Nom du codec Audio MPEG2 choisi +extern TCHAR filtreAudio[256]; //!< Nom du codec Audio MPEG2 choisi +extern TCHAR filtreAc3[256]; //!< Nom du codec AC3 choisi +extern TCHAR nomVille[256]; //!< Nom de la ville de l'utilisateur + +extern bool exact_match; //!< Indique si une correspondance exacte est souhaitée + //!< dans la recherche de filtres + +extern TCHAR nom_tuner[256]; //!< Nom du tuner à utiliser +extern TCHAR nom_receiver[256]; //!< Nom du récepteur à utiliser + +extern TCHAR screenshots_dir[MAX_PATH]; //!< Répertoire pour les captures d'écran +extern TCHAR video_dir[MAX_PATH]; //!< Répertoire pour les enregistrements vidéo +extern int avance_enreg; //!< Nombre de minutes d'anticipation du début enregistrements EPG +extern int retard_enreg; //!< Nombre de minutes de retard sur la fin des enregistrements EPG +extern int offset_tuner; //!< Offset à appliquer à toutes les fréquences recherchées +extern bool suspend_minimized; //!< Indique que le son doit être coupé en mode minimisé +extern bool minimize_system_tray; //!< Indique que la minimisation doit se faire dans la zone de notification +extern bool use_vmr_deinterlace; //!< \test Désentrelacement ; n'a sans doute jamais fonctionné +extern bool allow_stream_record; //!< Indique que l'enregistrement du multiplex entier est autorisé +extern bool use_msn; //!< Indique que l'affichage dans MSN est actif +extern bool on_top; //!< Indique que l'affichage doit se faire devant toutes les autres fenêtres +extern bool use_ac3; //!< Indique qu'on veut utiliser le codec AC3 quand il est disponible +extern bool use_osd; //!< true si l'OSD doit être utilisé +extern VMRTypes vmr_mode; //!< Indique le mode VMR à utiliser + +extern PanModes video_pan_mode; //!< Mode panoramique de la vidéo + //!< \todo Est-il vraiment opportun que ce mode soit sauvegardé ? + //!< (si oui, attention à la réinitialisation implicite quand on + //!< remet le zoom par défaut, ce qui nuit à la cohérence) +extern int zoom_ratio; //!< Facteur de zoom à appliquer à la vidéo + //!< \todo Est-il vraiment opportun que le zoom soit sauvegardé ? +extern long volumeCourant; //!< Niveau de volume sonore courant + +extern TCHAR motif_noms_enreg[MAX_PATH]; //!< Motifs pour les noms des enregistrements + +extern int epg_typerecvideo; //!< Type d'enregistrement précédement utilisé dans la + //!< fenêtre EPG pour la vidéo +extern int epg_typerecaudio; //!< Type d'enregistrement précédement utilisé dans la + //!< fenêtre EPG pour l'audio + +/** @} */ // fin de configVars + +// ==================================================================================== +// Fin des variables de configuration +// ==================================================================================== + /** * Définition des chemins de répertoires de base de l'application * (variables #pouchindir_prog et #pouchindir_conf), qui seront ensuite @@ -333,21 +393,6 @@ extern bool programmation_modifiee; /** - * Motifs pour les noms des enregistrements - **/ -extern TCHAR motif_noms_enreg[MAX_PATH]; - -/** - * Type d'enregistrement précédement utilisé dans la fenêtre epg pour la vidéo - **/ -extern int epg_typerecvideo; - -/** - * Type d'enregistrement précédement utilisé dans la fenêtre epg pour l'audio - **/ -extern int epg_typerecaudio; - -/** * Décrit un raccourci **/ struct Raccourci Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-01-16 15:25:32 UTC (rev 166) +++ trunk/main.cpp 2009-01-17 02:17:13 UTC (rev 167) @@ -57,21 +57,6 @@ HICON hRecIcon = NULL; //!< Icône utilisée en mode enregistrement static HWND hSignalDlg = NULL; //!< Handle de la fenêtre de qualité du signal -TCHAR filtreMPEG2[256]; -TCHAR filtreAudio[256]; -TCHAR filtreAc3[256]; -TCHAR nomVille[256]; -bool exact_match; - -TCHAR nom_tuner[256]; -TCHAR nom_receiver[256]; -int avance_enreg; -int retard_enreg; -int offset_tuner; - -TCHAR screenshots_dir[MAX_PATH]; -TCHAR video_dir[MAX_PATH]; - WORD numeroChaineSaisi = 0; WORD sidChaineConfig = 0; @@ -97,22 +82,10 @@ #define MENU_PROGRAMME_POSITION 6 #define SMENU_PRIORITE_POSITION 2 // dans menu "Programme" -bool use_msn = false; -bool on_top = false; -bool use_ac3 = false; -bool use_osd = true; -VMRTypes vmr_mode; -bool suspend_minimized = false; -bool minimize_system_tray = false; -bool allow_stream_record = false; -bool use_vmr_deinterlace = false; bool is_vista = false; OSVERSIONINFOEX windows_version; -PanModes video_pan_mode = pm_Normal; -int zoom_ratio = 100; - HACCEL hMainAccel = 0; bool shutdown_on_quit = false; @@ -2094,6 +2067,8 @@ break; case WM_APP_PMT_UPDATED: + myprintf(TEXT("Le pmt a changé\n")); + sauve_chaines(); zappe_index(ixChaineCourante); if (pOSD) pOSD->UpdateRectsAndFont(); Modifié: trunk/main.h =================================================================== --- trunk/main.h 2009-01-16 15:25:32 UTC (rev 166) +++ trunk/main.h 2009-01-17 02:17:13 UTC (rev 167) @@ -37,58 +37,13 @@ extern HWND hMainWnd; //!< Handle de la fenêtre principale de l'application extern HWND hMainStatus; //!< Handle de la barre d'état de l'application extern HMENU hMainMenu; //!< Handle de la barre de menus de l'application +extern HACCEL hMainAccel; //!< Accélérateur généré en runtime + extern HICON hPrgIcon; //!< Icône normale du programme extern HICON hRecIcon; //!< Icône utilisée en mode enregistrement -/** @defgroup configVars Variables de configuration - * Ces variables contiennent les données qui sont sauvegardées entre les sessions \p PouchinTVMod. - * elles sont chargées au démarrage de l'application, et sont sauvegardées chaque fois qu'une - * modification intervient dans l'une de celles-ci. - * \todo Autres éléments de configuration à prévoir : - * - Voir #OSD_COLOR, #OSD_TRANSPARENCY, #motif_noms_enreg. - * @{ - **/ +extern bool is_vista; //!< \p true si on est sous Windows Vista -extern TCHAR filtreMPEG2[256]; //!< Nom du codec Audio MPEG2 choisi -extern TCHAR filtreAudio[256]; //!< Nom du codec Audio MPEG2 choisi -extern TCHAR filtreAc3[256]; //!< Nom du codec AC3 choisi -extern TCHAR nomVille[256]; //!< Nom de la ville de l'utilisateur - -extern bool exact_match; //!< Indique si une correspondance exacte est souhaitée - //!< dans la recherche de filtres - -extern TCHAR nom_tuner[256]; //!< Nom du tuner à utiliser -extern TCHAR nom_receiver[256]; //!< Nom du récepteur à utiliser - -extern TCHAR screenshots_dir[MAX_PATH]; //!< Répertoire pour les captures d'écran -extern TCHAR video_dir[MAX_PATH]; //!< Répertoire pour les enregistrements vidéo -extern int avance_enreg; //!< Nombre de minutes d'anticipation du début enregistrements EPG -extern int retard_enreg; //!< Nombre de minutes de retard sur la fin des enregistrements EPG -extern int offset_tuner; //!< Offset à appliquer à toutes les fréquences recherchées -extern bool suspend_minimized; //!< Indique que le son doit être coupé en mode minimisé -extern bool minimize_system_tray; //!< Indique que la minimisation doit se faire dans la zone de notification -extern bool use_vmr_deinterlace; //!< \test Désentrelacement ; n'a sans doute jamais fonctionné -extern bool allow_stream_record; //!< Indique que l'enregistrement du multiplex entier est autorisé -extern bool use_msn; //!< Indique que l'affichage dans MSN est actif -extern bool on_top; //!< Indique que l'affichage doit se faire devant toutes les autres fenêtres -extern bool use_ac3; //!< Indique qu'on veut utiliser le codec AC3 quand il est disponible -extern bool use_osd; //!< true si l'OSD doit être utilisé -extern VMRTypes vmr_mode; //!< Indique le mode VMR à utiliser - -extern PanModes video_pan_mode; //!< Mode panoramique de la vidéo - //!< \todo Est-il vraiment opportun que ce mode soit sauvegardé ? - //!< (si oui, attention à la réinitialisation implicite quand on - //!< remet le zoom par défaut, ce qui nuit à la cohérence) -extern int zoom_ratio; //!< Facteur de zoom à appliquer à la vidéo - //!< \todo Est-il vraiment opportun que le zoom soit sauvegardé ? -extern long volumeCourant; //!< Niveau de volume sonore courant - -extern HACCEL hMainAccel; //!< Accélérateur généré en runtime - -/** @} */ // fin de configVars - -extern bool is_vista; //!< true si on est sous Windows Vista - /// diverses informations sur la version de windows (utile plus tard ?) extern OSVERSIONINFOEX windows_version; Modifié: trunk/pmtfilter.cpp =================================================================== --- trunk/pmtfilter.cpp 2009-01-16 15:25:32 UTC (rev 166) +++ trunk/pmtfilter.cpp 2009-01-17 02:17:13 UTC (rev 167) @@ -51,16 +51,16 @@ CUnknown * WINAPI CPMTFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr) // static { - CPMTFilter *pNewFilter = new CPMTFilter(pUnk, phr); + CPMTFilter *pNewFilter = new CPMTFilter(pUnk, phr); - if (phr) { - if (pNewFilter == NULL) - *phr = E_OUTOFMEMORY; - else - *phr = S_OK; - } + if (phr) { + if (pNewFilter == NULL) + *phr = E_OUTOFMEMORY; + else + *phr = S_OK; + } - return pNewFilter; + return pNewFilter; } HRESULT CPMTFilter::DoRenderSample(IMediaSample *pMediaSample) @@ -83,11 +83,10 @@ parse_pmt(*ppmt, false, lpmt_e/*, false*/); if (lpmt_e != chaine) { // "operator !=" maintenant implémenté - myprintf(TEXT("Le pmt a changé\n")); chaine = lpmt_e; - sauve_chaines(); - // dit de rezapper sur cette chaîne + // Notifier du changement de PMT (demande de rezapper + // sur cette chaîne, et de sauvegarder les modifications) PostMessage(hMainWnd, WM_APP_PMT_UPDATED, 0, 0); } } Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2009-01-16 15:25:32 UTC (rev 166) +++ trunk/recprog.cpp 2009-01-17 02:17:13 UTC (rev 167) @@ -53,13 +53,13 @@ std::vector Programmes; -static HWND hRecordDlg = NULL; -static wchar_t mdp[256] = L""; +static HWND hRecordDlg = NULL; +static WCHAR mdp[256] = L""; // Variables utilisées pendant les modifications des contrôles date et heure pour tester la // différence entre le début et la fin ainsi que la différence avec la valeur avant changement : -static SYSTEMTIME dtc_debut = {0}; -static SYSTEMTIME dtc_fin = {0}; +static SYSTEMTIME dtc_debut = {0}; +static SYSTEMTIME dtc_fin = {0}; /** * On passe un SID de chaîne en paramètre, @@ -82,15 +82,19 @@ case WM_COMMAND: switch(LOWORD(wParam)) { - case IDOK: - char buffer[256]; - buffer[0] = 127; - SendDlgItemMessage(hwndDlg, IDC_PASWD, EM_GETLINE, 0, (LPARAM)buffer); - for(int i = 1; buffer[2 * (i - 1)] != 0; i++) - buffer[i] = buffer[2 * i]; + + case IDOK: { + TCHAR buffer[128]; + + *reinterpret_cast(&buffer[0]) = _countof(buffer); + + UINT nLen = (UINT)SendDlgItemMessage(hwndDlg, IDC_PASWD, EM_GETLINE, 0, (LPARAM)buffer); + + buffer[nLen] = 0; // (selon la doc, EM_GETLINE n'ajouterait pas toujours le zéro terminateur) strcpy_T(mdp, buffer); EndDialog(hwndDlg, 0); - return TRUE; + return TRUE; } + case IDCANCEL: EndDialog(hwndDlg, 1); return TRUE; @@ -141,15 +145,21 @@ DiffTime(p2.fin, debut) >= DUREE_MARGE_RECOUVREMENT; } -// Utilisé par la fonction std::sort : +/** + * \brief Comparaison en vue de tri sur l'heure de début + * + * Utilisé par la fonction std::sort + * \retval \p true si cette programmation se classe avant la programmation \p p2 dans le temps. + **/ bool Programme::operator < (const Programme & p2) const { return DiffTime(debut, p2.debut)<0; } /** - * Calcul du temps restant avant début enregistrement en millisecondes. - * L'heure de référence (en principe l'heure système) doit être passée en paramètre. + * \brief Calcul du temps restant avant début enregistrement en millisecondes. + * + * \param[in] localtime Heure de référence (en principe l'heure système) **/ long Programme::temps_restant(const SYSTEMTIME & localtime) const { @@ -162,16 +172,20 @@ } /** - * Ajustement des données si répétitions programmées et horaire de fin dépassé. - * L'heure de référence (en principe l'heure système) doit être passée en paramètre. - * Retourne 'true' si un ajustement a eu lieu + * \brief Ajustement des données si répétitions programmées et horaire de fin dépassé + * + * \param[in] localtime Heure de référence (en principe l'heure système) + * \retval \p true si un ajustement a eu lieu **/ -bool Programme::ajustementDesRepetitions(const SYSTEMTIME & time) +bool Programme::ajustementDesRepetitions(const SYSTEMTIME & localtime) { bool res = false; - if (repetition!=0 && !active()) { - while (DiffTime(fin, time) <= 0) { + if (repetition != 0 && etat != epr_inactif) { + // En cas de répétition, tous les enregistrements non explicitement marqués comme + // "inactifs" sont reconduits et réactivés dès lors que l'heure de fin est dépassée + + while (DiffTime(localtime, fin) >= 0) { // Tant que l'heure de fin est dépassée int nbJours; // Trouver le nombre de jours avant la répétition suivante : @@ -199,9 +213,10 @@ } /** - * Vérification de la validité de la programmation 'prog' - * (mettre 'modif' à 'true' si on est en train de modifier une programmation) - * Retourne true si ok, false si erreur. + * \brief Vérification de la validité de la programmation + * + * \param[in] modif Mettre à \p true si on est en train de modifier une programmation + * \retval \p true ou \p false selon succès ou échec, respectivement **/ bool Programme::verifie(bool modif) const { @@ -282,8 +297,12 @@ return true; // pas d'erreur } - -// Génération du nom de tâche programmée correspondant +/** + * \brief Génération du nom de tâche programmée correspondant + * + * \param[in] pstr Pointeur sur le tampon qui va recevoir le nom + * \param[in] bufSize Taille de ce tampon + **/ void Programme::genereNomTache(LPWSTR pstr, UINT bufSize) const { // Remplace les caracteres incorrects : @@ -299,7 +318,13 @@ nom_tache.Extract(pstr, bufSize); } -// Ajout de cette programmation aux tâches programmées (retourne 'false' si échec) +/** + * \brief Ajout de cette programmation aux tâches programmées + * + * \param[in] username Nom d'utilisateur + * \param[in] motdepasse Mot de passe + * \retval \p true ou \p false selon succès ou échec, respectivement + **/ bool Programme::ajouterTacheProgrammee(LPCWSTR username, LPCWSTR motdepasse) const { WCHAR taskName[_countof(nom)+4]; @@ -398,8 +423,10 @@ } /** - * Ajout de la programmation si nécessaire, incluant identification - * Retourne 'true' si une programmation a effectivement été réalisée + * \brief Ajout de la programmation si nécessaire, incluant identification + * + * \param[in] hDlg Handle du dialogue parent + * \retval \p true ou \p false selon succès ou échec, respectivement **/ bool Programme::ajoutTacheAvecLogon(HWND hDlg) { @@ -408,7 +435,7 @@ supprimerTacheProgrammee(); if (etat==epr_actif && tache == planif_ajout) { - wchar_t username[256]; + WCHAR username[256]; DWORD iLen = _countof(username); GetUserNameW(username, &iLen); // Obtenir le nom de l'utilisateur courant @@ -429,7 +456,11 @@ return false; } -// Supprimer cette programmation des tâches programmées (retourne 'false' si échec) +/** + * \brief Suppression de cette programmation de la liste des tâches programmées + * + * \retval \p true ou \p false selon succès ou échec, respectivement + **/ bool Programme::supprimerTacheProgrammee() const { WCHAR taskName[_countof(nom)+4]; @@ -452,7 +483,7 @@ /** * Traitement du chargement de la liste des programmes au démarrage, et purge - * des enregistrements périmés : + * des enregistrements périmés **/ void init_programmation() { @@ -481,14 +512,17 @@ i++; } - // Sauvegarde à nouveau la liste des programmes - if (programmation_modifiee) - sauve_programmes(); + // Mises à jour éventuelles au cas où les opérations + // précédentes auraient modifié la programmation + record_list_updated(); } /** - * Trouver l'index de l'enregistrement programmé dont le nom est 'nom'. - * Retourne -1 si nom vide ou rien trouvé. + * Trouver l'index d'un enregistrement programmé à partir de son nom + * + * \param[in] nom Nom de l'enregistrement recherché + * \retval Index numérique de l'enregistrement + * \retval -1 si nom vide ou rien trouvé. **/ int trouve_prog_par_nom(LPCTSTR nom) { @@ -1278,8 +1312,8 @@ /** * Traitement des événements liés au dialogue d'enregistrement. - * Retourne 'true' si le message 'msg' a été traité, auquel cas il ne faut pas le - * passer à TranslateMessage et DispatchMessage. + * Retourne \p true si le message \p msg a été traité, auquel cas il ne faut pas le + * passer à \p TranslateMessage et \p DispatchMessage. * À placer dans la boucle de gestion générale des messages. **/ bool is_record_dialog_message(MSG & msg) { @@ -1598,7 +1632,16 @@ return TRUE; case _cmd_(IDC_AFTER, BN_CLICKED): + // Décoche le bouton arrêtant le PC si on ne souhaite pas arrêter PouchinTV + if (IsDlgButtonChecked(hDlg, IDC_AFTER) == BST_UNCHECKED) + CheckDlgButton(hDlg, IDC_AFTER_POWEROFF, BST_UNCHECKED); + edat.setChangedState(des_needConfirm); + return TRUE; + case _cmd_(IDC_AFTER_POWEROFF, BN_CLICKED): + // Coche le bouton arrêtant PouchinTV si on a demandé l'arrêt de l'ordinateur + if (IsDlgButtonChecked(hDlg, IDC_AFTER_POWEROFF) == BST_CHECKED) + CheckDlgButton(hDlg, IDC_AFTER, BST_CHECKED); edat.setChangedState(des_needConfirm); return TRUE; @@ -1835,8 +1878,10 @@ } /** - * Exécution de toutes les transitions d'enregistrements qui devraient être assurées à cet instant. - * Retourne 'true' si au moins une transition (démarrage, arrêt, erreur...) a eu lieu. + * Exécution de toutes les transitions d'enregistrements (démarrage, + * arrêt, erreur...) qui devraient être assurées à cet instant. + * + * \retval \p true si au moins une transition a eu lieu dans la fonction **/ bool do_record_events() { Modifié: trunk/recprog.h =================================================================== --- trunk/recprog.h 2009-01-16 15:25:32 UTC (rev 166) +++ trunk/recprog.h 2009-01-17 02:17:13 UTC (rev 167) @@ -30,44 +30,49 @@ #include "base.h" #include "ini.h" +/// Spécification de la méthode d'enregistrement enum MethodeEnregistrement { - meth_TS, // 0 - meth_PS, // 1 - meth_multiplex // 2 + meth_TS, //!< 0: L'enregistrement s'effectuera en mode TS + meth_PS, //!< 1: L'enregistrement s'effectuera en mode PS + meth_multiplex //!< 2: Le multiplex entier sera enregistré }; +/// Indique quoi faire après un enregitrement enum ApresEnregistrement { - apr_null = -1, // utilisé dans les enregistrements en cours, pour indiquer - // qu'aucun horaire de fin n'est associé à un enregistrement - apr_rien = 0, // 0 - apr_quitter, // 1 - apr_eteindrePC, // 2 + apr_null = -1, //!< -1: Utilisé dans les enregistrements en cours, pour indiquer + //!< qu'aucun horaire de fin n'est associé à un enregistrement + apr_rien = 0, //!< 0: On ne fait rien + apr_quitter, //!< 1: On quitte l'application + apr_eteindrePC, //!< 2: On quitte l'application et on éteint l'ordinateur }; +/// Indique quelle piste audio sera utilisée dans un enregistrement enum AudioMode { - audio_1, - audio_2, - audio_AC3 + audio_1, //!< Utilisation de la première piste MPEG2 disponible + audio_2, //!< Utilisation de la seconde piste MPEG2 disponible + audio_AC3 //!< Utilisation de la première piste AC3 disponible }; +/// Statut d'un enregistrement par rapport au planificateur de tâches enum PlanificateurTache { - planif_sans, // 0: non planifiée - planif_avec, // 1: planifiée (ajout effectué) - planif_ajout // 2: planifiée (à ajouter au planificateur lors de la validation) + planif_sans, //!< 0: non planifiée + planif_avec, //!< 1: planifiée (ajout effectué) + planif_ajout //!< 2: planifiée (à ajouter au planificateur lors de la validation) }; +/// État d'activation d'un enregistrement programmé enum EtatProgramme { - epr_actif, - epr_encours, - epr_inactif, // désactivé par l'utilisateur - epr_interrompu, // manuellement arrêté après démarrage - epr_supplante, // si heure de fin modifiée après démarrage - epr_termine, // heure de fin atteinte - epr_erreur, - epr_null = -1 // pseudo-valeur pour dire "ne pas modifier" + epr_actif, //!< L'enregistrement est actif (programmé et à venir) + epr_encours, //!< L'enregistrement en cours + epr_inactif, //!< Désactivé par l'utilisateur + epr_interrompu, //!< Manuellement arrêté après démarrage + epr_supplante, //!< Heure de fin modifiée après démarrage + epr_termine, //!< Heure de fin atteinte + epr_erreur, //!< Une erreur s'est produite + epr_null = -1 //!< Pseudo-valeur pour dire "ne pas modifier" }; -typedef TCHAR NomProg[64]; // Type pour nom donné à une programmation +typedef TCHAR NomProg[64]; //!< Type pour nom donné à une programmation // Structure commune aux programmations d'enregistrement et aux enregistrements en cours : class RecordInfo @@ -85,66 +90,110 @@ RecordInfo() {memset(this, 0, sizeof(*this)); apres = apr_null;} }; +/// Définition d'une programmation d'enregistrement class Programme : public RecordInfo { public: - SYSTEMTIME debut; // Date & heure de début + SYSTEMTIME debut; //!< Date & heure de début - // Registre de bits contenant les répétitions des enregistrements : - // 0: Dimanche, 1: Lundi, ...., 6: Samedi + /** + * \brief Registre de bits indiquant les jours de répétition des enregistrements + * + * (bit 0: Dimanche, bit 1: Lundi, ...., bit 6: Samedi) + **/ BYTE repetition; - PlanificateurTache tache; - EtatProgramme etat; - bool nomAuto; // 'true' si nom généré automatiquement + PlanificateurTache tache; //!< Statut au regard du planificateur de tâches + EtatProgramme etat; //!< État (d'activation) de la programmation + bool nomAuto; //!< \p true si nom généré automatiquement - // Mini-constructeur : + /// Constructeur Programme(); - // Méthodes : + /** + * \brief Vérification de la validité de la programmation + * + * \param[in] modif Mettre à \p true si on est en train de modifier une programmation + * \retval \p true ou \p false selon succès ou échec, respectivement + * \todo Ne plus interdire les programmations incompatibles pour cause de recouvrement + * d'horaires. Se contenter de produire un avertissement qui peut être ignoré (laissant + * ainsi à l'utilisateur la possibilité de résoudre l'incompatibilité a posteriori). + **/ + bool verifie(bool modif) const; - // Vérification de la validité de la programmation - // (mettre 'modif' à 'true' si on est en train de modifier une programmation) - bool verifie(bool modif) const; + /** + * \brief Calcul du temps restant avant début enregistrement en millisecondes. + * + * \param[in] localtime Heure de référence (en principe l'heure système) + **/ + long temps_restant(const SYSTEMTIME & localtime) const; - // Calcul du temps restant avant début enregistrement en millisecondes. - // L'heure de référence (en principe l'heure système) doit être passée en paramètre. - long temps_restant(const SYSTEMTIME & time) const; + /** + * \brief Ajustement des données si répétitions programmées et horaire de fin dépassé + * + * \param[in] localtime Heure de référence (en principe l'heure système) + * \retval \p true si un ajustement a eu lieu + **/ + bool ajustementDesRepetitions(const SYSTEMTIME & localtime); - // Ajustement des données si répétitions programmées et horaire de fin dépassé - // L'heure de référence (en principe l'heure système) doit être passée en paramètre. - // Retourne 'true' si un ajustement a eu lieu - bool ajustementDesRepetitions(const SYSTEMTIME & time); + /** + * \brief Ajout de cette programmation aux tâches programmées + * + * \param[in] username Nom d'utilisateur + * \param[in] motdepasse Mot de passe + * \retval \p true ou \p false selon succès ou échec, respectivement + **/ + bool ajouterTacheProgrammee(LPCWSTR username, LPCWSTR motdepasse) const; - // Ajout de cette programmation aux tâches programmées (retourne 'false' si échec) - bool ajouterTacheProgrammee(LPCWSTR username, LPCWSTR motdepasse) const; + /** + * \brief Suppression de cette programmation de la liste des tâches programmées + * + * \retval \p true ou \p false selon succès ou échec, respectivement + **/ + bool supprimerTacheProgrammee() const; - // Supprimer cette programmation des tâches programmées (retourne 'false' si échec) - bool supprimerTacheProgrammee() const; + /** + * \brief Ajout de la programmation si nécessaire, incluant identification + * + * \param[in] hDlg Handle du dialogue parent + * \retval \p true ou \p false selon succès ou échec, respectivement + **/ + bool ajoutTacheAvecLogon(HWND hDlg); - // Ajout de la programmation si nécessaire, incluant identification - bool ajoutTacheAvecLogon(HWND hDlg); + /** + * \brief Génération du nom de tâche programmée correspondant + * + * \param[in] pstr Pointeur sur le tampon qui va recevoir le nom + * \param[in] bufSize Taille de ce tampon + **/ + void genereNomTache(LPWSTR pstr, UINT bufSize) const; - // Génération du nom de tâche programmée correspondant - void genereNomTache(LPWSTR pstr, UINT bufSize) const; + /** + * \brief Obtenir le nom du jour de la semaine du début de l'enregistrement + * + * \retval Pointeur sur une chaîne de caractère qui représente ce nom + **/ + LPCTSTR startDoW() const { + return debut.wDayOfWeek<7 ? Tbl_DoW[debut.wDayOfWeek] : TEXT("?");} - // Obtenir le nom du jour de la semaine du début de l'enregistrement : - LPCTSTR startDoW() const - {return debut.wDayOfWeek<7 ? Tbl_DoW[debut.wDayOfWeek] : TEXT("?");} + /// Retourne \p true si la programmation est couramment active + bool active() const { + return etat==epr_actif || etat==epr_encours;} - // Retourne 'true' si la programmation est couramment active : - bool active() const - {return etat==epr_actif || etat==epr_encours;} + /// Retourne \p true si intersection temporelle avec la programmation \p p2 + bool overlap(const Programme & p2) const; - // Retourne 'true' si intersection temporelle avec la programmation 'p2' - bool overlap(const Programme & p2) const; + /// Retourne \p true si on a affaire à une programmation d'enregistrement de multiplex + bool isMultiplex() const { + return methode==meth_multiplex;} - // Retourne 'true' si on a affaire à une programmation d'enregistrement de multiplex - bool isMultiplex() const - {return methode==meth_multiplex;} - - // Utilisé par la fonction std::sort : - bool operator < (const Programme & p2) const; + /** + * \brief Comparaison en vue de tri sur l'heure de début + * + * Utilisé par la fonction std::sort + * \retval \p true si cette programmation se classe avant la programmation \p p2 dans le temps. + **/ + bool operator < (const Programme & p2) const; }; extern std::vector Programmes; @@ -152,8 +201,6 @@ /** * Traitement du chargement de la liste des programmes au démarrage, et purge * des enregistrements périmés - * \todo S'assurer que sont purgés aussi (par changement de date) les enregistrements - * avec répétitions, lorsque l'une de ces répétitions n'a pas pu être traitée. **/ void init_programmation(); @@ -169,8 +216,8 @@ /** * Traitement des événements liés au dialogue d'enregistrement. - * Retourne 'true' si le message 'msg' a été traité, auquel cas il ne faut pas le - * passer à TranslateMessage et DispatchMessage. + * Retourne \p true si le message \p msg a été traité, auquel cas il ne faut pas le + * passer à \p TranslateMessage et \p DispatchMessage. * À placer dans la boucle de gestion générale des messages. **/ bool is_record_dialog_message(MSG & msg); @@ -195,8 +242,10 @@ //void do_record_stop(int grab); /** - * Exécution de toutes les transitions d'enregistrements qui devraient être assurées à cet instant. - * Retourne 'true' si au moins une transition (démarrage, arrêt, erreur...) a eu lieu. + * Exécution de toutes les transitions d'enregistrements (démarrage, + * arrêt, erreur...) qui devraient être assurées à cet instant. + * + * \retval \p true si au moins une transition a eu lieu dans la fonction **/ bool do_record_events(); @@ -206,8 +255,11 @@ bool chaineToProg(int ixChaine, BYTE noEmis, Programme & prog); /** - * Trouver l'index de l'enregistrement programmé dont le nom est 'nom'. - * Retourne -1 si nom vide ou rien trouvé. + * Trouver l'index d'un enregistrement programmé à partir de son nom + * + * \param[in] nom Nom de l'enregistrement recherché + * \retval Index numérique de l'enregistrement + * \retval -1 si nom vide ou rien trouvé. **/ int trouve_prog_par_nom(LPCTSTR nom); Modifié: trunk/rendering.cpp =================================================================== --- trunk/rendering.cpp 2009-01-16 15:25:32 UTC (rev 166) +++ trunk/rendering.cpp 2009-01-17 02:17:13 UTC (rev 167) @@ -1465,10 +1465,6 @@ if (SUCCEEDED(hr)) { hr = pVMR->Connect(pVideoCodec); -#ifdef TEST_H264 - if (SUCCEEDED(hr)) - hr = pVMR->Connect(pVideoH264Codec); -#endif if (SUCCEEDED(hr) && eState==State_Running) hr = graph_Run(); } From pouchintv-dev at baysse.fr Sat Jan 17 20:16:16 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sat, 17 Jan 2009 20:16:16 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r168 - trunk Message-ID: <20090117191616.4E1526EED2@mail.baysse.fr> Author: gingko Date: 2009-01-17 20:16:15 +0100 (sam, 17 jan 2009) New Revision: 168 Modified: trunk/graph.cpp trunk/ini.cpp trunk/ini.h trunk/main.cpp trunk/main.h trunk/rendering.cpp trunk/rendering.h trunk/res.rc trunk/resource.h trunk/settings.cpp trunk/update.h Log: Réorganisation de la gestion générale du programme (initialisation, exécution, terminaison) : il est maintenant possible de modifier les codecs utilisés ou bien le moteur de rendu vidéo (VMR) sans avoir ensuite à relancer l'application (sauf si un ou plusieurs enregistrements sont en cours). main.cpp : * Création des fonctions CleanTemporaryFiles, CheckForExistingInstance, InitInstance, CleanInstance, CreateMainWindow et MainTask pour isoler des groupes d'instructions spécifiques précédemment inclus dans WinMain et les rendre plus modulaires. * Réarrangement de l'ordre d'initialisation générale du programme. Par exemple, il n'était pas toujours garanti que les fonctions "myprintf" (debugging) soient appelées après l'ouverture de la console de debugging ... * La tâche principale (incluant la gestion du graphe) est placée dans une boucle qui permet de la lancer plusieurs fois sans avoir à quitter le programme. ini.h, ini.cpp, main.cpp : * Ajout d'une option de configuration pour activer ou désactiver le va-et-vient de fréquences au démarrage, nécessaire à certains tuners mais pas à d'autres : ce traitement demandant parfois quelques secondes, il n'est pas opportun de l'imposer à ceux qui n'en ont pas besoin. * Déplacement de la variable de configuration "sidChaineConfig" dans le groupe des variables de configuration (oubli de la livraison précédente) rendering.h, rendering.cpp, main.cpp : * La création et la destruction des objets OSD est maintenant liée à celle du VMR. settings.cpp : * Correctif d'une régression (introduite par moi à la r141, j'avoue), qui faisait que la renumérotation automatique des chaînes ne fonctionnait plus. Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/graph.cpp 2009-01-17 19:16:15 UTC (rev 168) @@ -177,10 +177,7 @@ pDemux.Release(); - if (pVMR) { - delete pVMR; - pVMR = NULL; - } + clean_vmr(); pDSound.Release(); pDSoundAc3.Release(); @@ -852,7 +849,7 @@ #endif case EC_VIDEO_SIZE_CHANGED: // 0x0a - PostMessage(hWnd, WM_VIDEO_SIZE_CHANGED, 0, 0); + PostMessage(hWnd, WM_APP_VIDEOSIZE_CHG, 0, 0); myprintf(TEXT("Nouvelle taille vidéo = %u/%u\n"), LOWORD(param1), HIWORD(param1)); break; Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/ini.cpp 2009-01-17 19:16:15 UTC (rev 168) @@ -129,9 +129,11 @@ TCHAR screenshots_dir[MAX_PATH]; TCHAR video_dir[MAX_PATH]; +WORD sidChaineConfig = 0; int avance_enreg; int retard_enreg; int offset_tuner; +bool verif_freq_demarrage = false; bool suspend_minimized = false; bool minimize_system_tray = false; bool use_vmr_deinterlace = false; @@ -233,6 +235,7 @@ static TCHAR ini_use_osd[] = TEXT("Utiliser l'OSD"); static TCHAR ini_video_rendering[] = TEXT("Rendu vidéo"); static TCHAR ini_suspend_minimized[] = TEXT("Suspendre si minimisé"); +static TCHAR ini_verif_freq_demarrage[] = TEXT("Palliatif bug démarrage"); static TCHAR ini_minimize_system_tray[] = TEXT("Minimiser dans le system tray"); static TCHAR ini_allow_stream_record[] = TEXT("Enregistrement multiplex autorisé"); static TCHAR ini_video_pan_mode[] = TEXT("Panoramique"); @@ -1239,6 +1242,7 @@ save_config_bool(ini_use_osd, use_osd); save_config_assoc(ini_video_rendering, aVMRModeTable, vmr_mode); save_config_bool(ini_suspend_minimized, suspend_minimized); + save_config_bool(ini_verif_freq_demarrage, verif_freq_demarrage); save_config_bool(ini_minimize_system_tray, minimize_system_tray); save_config_bool(ini_allow_stream_record, allow_stream_record); save_config_assoc(ini_video_pan_mode, aPanModeTable, video_pan_mode); @@ -1531,6 +1535,7 @@ use_osd = load_config_bool(ini_use_osd, true); vmr_mode = (VMRTypes)load_config_assoc(ini_video_rendering, aVMRModeTable, vmt_VMR9_windowless); suspend_minimized = load_config_bool(ini_suspend_minimized); + verif_freq_demarrage = load_config_bool(ini_verif_freq_demarrage, true); minimize_system_tray = load_config_bool(ini_minimize_system_tray); allow_stream_record = load_config_bool(ini_allow_stream_record); use_vmr_deinterlace = load_config_bool(ini_use_vmr_deinterlace); Modifié: trunk/ini.h =================================================================== --- trunk/ini.h 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/ini.h 2009-01-17 19:16:15 UTC (rev 168) @@ -109,9 +109,12 @@ extern TCHAR screenshots_dir[MAX_PATH]; //!< Répertoire pour les captures d'écran extern TCHAR video_dir[MAX_PATH]; //!< Répertoire pour les enregistrements vidéo + +extern WORD sidChaineConfig; //!< SID chaîne courante extern int avance_enreg; //!< Nombre de minutes d'anticipation du début enregistrements EPG extern int retard_enreg; //!< Nombre de minutes de retard sur la fin des enregistrements EPG extern int offset_tuner; //!< Offset à appliquer à toutes les fréquences recherchées +extern bool verif_freq_demarrage; //!< Vérification de fréquence au démarrage extern bool suspend_minimized; //!< Indique que le son doit être coupé en mode minimisé extern bool minimize_system_tray; //!< Indique que la minimisation doit se faire dans la zone de notification extern bool use_vmr_deinterlace; //!< \test Désentrelacement ; n'a sans doute jamais fonctionné Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/main.cpp 2009-01-17 19:16:15 UTC (rev 168) @@ -58,7 +58,6 @@ static HWND hSignalDlg = NULL; //!< Handle de la fenêtre de qualité du signal WORD numeroChaineSaisi = 0; -WORD sidChaineConfig = 0; static bool muted = false; //!< Sourdine @@ -80,14 +79,14 @@ #define MENU_PISTES_POSITION 4 #define MENU_CAPTURES_POSITION 5 #define MENU_PROGRAMME_POSITION 6 -#define SMENU_PRIORITE_POSITION 2 // dans menu "Programme" +#define SMENU_PRIORITE_POSITION 2 // dans menu "Programme" -bool is_vista = false; - +bool is_vista = false; //!< \p true si on est sous Windows Vista OSVERSIONINFOEX windows_version; HACCEL hMainAccel = 0; +bool bNeedRestart = false; //!< \p true si l'application doit être relancée bool shutdown_on_quit = false; #ifdef USE_LOGITECH_LCD @@ -1108,12 +1107,10 @@ static void create_status_bar(void) { - //hMainStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE, L"chaîne", hMainWnd, 41234); - // Create the status bar. - hMainStatus = CreateWindowExA( + hMainStatus = CreateWindowEx( 0, // no extended styles - STATUSCLASSNAMEA, // name of status bar class + STATUSCLASSNAME, // name of status bar class NULL, // no text when first created WS_CHILD | WS_VISIBLE, // creates a child window 0, 0, 0, 0, // ignores size and position @@ -1121,10 +1118,6 @@ (HMENU) 41234, // child window identifier hAppInstance, // handle to application instance NULL); // no window creation data - - - update_status_size(); - update_status_bar(); } static bool remove_borders() @@ -1149,6 +1142,8 @@ if (hMainStatus==NULL) { create_status_bar(); + update_status_size(); + update_status_bar(); change = true; } if (GetMenu(hMainWnd)==NULL) { @@ -1176,12 +1171,14 @@ UINT newShowCmd = wpl.showCmd; switch (nouvel_etat) { + case etf_normal: nouveau_style |= WS_OVERLAPPEDWINDOW; newShowCmd = SW_SHOWNORMAL; if (restore_borders()) change = true; break; + case etf_noborders: nouveau_style &= ~WS_OVERLAPPEDWINDOW; nouveau_style |= WS_THICKFRAME; @@ -1189,12 +1186,14 @@ if (remove_borders()) change = true; break; + case etf_maximized: nouveau_style |= WS_OVERLAPPEDWINDOW; newShowCmd = SW_SHOWMAXIMIZED; if (restore_borders()) change = true; break; + case etf_fullscreen: nouveau_style &= ~WS_OVERLAPPEDWINDOW; newShowCmd = SW_SHOWMAXIMIZED; @@ -1213,6 +1212,7 @@ change = true; nouveau_curseur = etc_fullscreen_on; break; + case etf_minimized: nouveau_style |= WS_OVERLAPPEDWINDOW; newShowCmd = SW_SHOWMINIMIZED; @@ -1408,6 +1408,20 @@ case IDM_CONFIG: do_config(hMainWnd); update_record_menus(hMainWnd); // Mise à jour des menus "Chaînes" et "Programme" + // Si les changements dans la configuration requièrent que l'application soit relancée, + // on quitte (la relance sera automatique) + if (bNeedRestart) { + if (recording()!=0) { + MessageBox(hMainWnd, + TEXT("Au moins un enregistrement est en cours :\n") + TEXT("Certaines des modifications apportées à la configuration\n") + TEXT("ne s'appliqueront qu'après redémarrage de l'application."), + TEXT("Paramètres modifiés"), MB_ICONINFORMATION); + bNeedRestart = false; + } else + // Redémarrage (partiel) de l'application + PostMessage(hMainWnd, WM_APP_RESTART, 0, 0); + } break; @@ -1805,25 +1819,21 @@ // ShowWindow(hWnd, SW_RESTORE); if (recording()!=0) { // Si on enregistre, affiche la fenêtre de confirmation - if (DialogBox(hAppInstance, MAKEINTRESOURCE(IDD_CLOSE_CONFIRM), hWnd, ConfirmCloseProc) == 0) + if (DialogBox(hAppInstance, MAKEINTRESOURCE(IDD_CLOSE_CONFIRM), hWnd, ConfirmCloseProc) == 0) { + bNeedRestart = false; // (précaution, car déjà protégé ailleurs) break; // On a appuyé sur Annuler, donc, on ne quitte pas + } } DestroyWindow(hWnd); break; case WM_DESTROY: save_config(); + PostQuitMessage(0); + break; - // Je mets ceci (temporairement ... ??) à cause d'un problème que je rencontre parfois, - // où on voit PouchinTV quitter tout en restant comme "zombie", - // mais consommant toutes les ressources, dans le système. - // Au moins ainsi ça devrait éviter de bloquer l'ordinateur - // si le programme tournait en priorité élevée. - // À virer quand ce problème aura été résolu, donc. - Gingko - set_priority(IDLE_PRIORITY_CLASS); - - clean_dshow(); - niData.disable(); + case WM_APP_RESTART: + bNeedRestart = true; PostQuitMessage(0); break; @@ -2078,7 +2088,7 @@ HandleGraphEvent(hMainWnd); break; - case WM_VIDEO_SIZE_CHANGED: + case WM_APP_VIDEOSIZE_CHG: if (pOSD) pOSD->UpdateRectsAndFont(); break; @@ -2160,10 +2170,12 @@ } /// Liste énumérative pour l'ordre des paramètres de la ligne de commande -/// \todo Trouver une stratégie cohérente pour le cas où une option --recps ou --rects -/// spécifiée entrerait en conflit avec un enregistrement programmé -/// (par exemple : si par ailleurs un enregistrement programmé existe et se trouve -/// à devoir être lancé immédiatement) +/// \todo Concernant les options de ligne de commande : +/// - Trouver une stratégie cohérente pour le cas où une option --recps ou --rects +/// spécifiée entrerait en conflit avec un enregistrement programmé +/// (par exemple : si par ailleurs un enregistrement programmé existe et se trouve +/// à devoir être lancé immédiatement) +/// - implémenter quelque chose pour l'option "--help" enum eCmdOption { cmd_minimize_old, // Alias de compatibilité cmd_minimize, @@ -2286,125 +2298,114 @@ return valeurs; } -int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +/** + * Effacement des fichiers dont le nom se finit par « _ », dans le dossier actuel de PTVM + * \todo Faire en sorte que ces fichiers ne se trouvent pas dans le dossier de l'application. + * Normalement, l'application ne doit pas pouvoir modifier quoi que ce soit dans son propre + * dossier : en effet, le dossier d'application n'est normalement pas accessible en écriture + * dans les comptes limités (non administrateurs). + * La mise à jour de l'application elle-même devrait sans doute être la seule exception possible. + **/ +void CleanTemporaryFiles() { - // Définition des répertoires de base de l'application - ini_app_paths(); + // Regarde si un fichier dont le nom se finit par « _ » existe dans le dossier actuel de PTVM + WIN32_FIND_DATA fd = {0}; // Pour rechercher les fichiers + TCHAR chemin[MAX_PATH]; // Dossier actuel + pattern pour la recherche de fichiers de mise à jour - { - // Première chose à faire: - // Vérifier si une autre instance ne fonctionne pas déjà - HANDLE hMutex = CreateMutex(NULL, TRUE, szAppName); + strcpy_T(chemin, pouchindir_prog); + strcat_T(chemin, TEXT("*_")); + // On recherche + HANDLE hSearch = FindFirstFile(chemin, &fd); - bool bQuitte = true, // Indique qu'il faut quitter - bMutexError = (GetLastError()==ERROR_ALREADY_EXISTS); // Mutex déjà existant + if (hSearch != INVALID_HANDLE_VALUE) { - // On attend 3 secondes la libération du mutex - // Pas plus longtemps, car si ce n'est pas une mise à jour, l'utilisateur l'a appelé 2 fois, - // et donc, si c'est plus long avant de réafficher la fenêtre principale, celui-ci - // risque de le rapeller une fois de plus - DWORD res = WaitForSingleObject(hMutex, 3*1000); + // On efface les fichiers dont le nom se finit par « _ » + do { + _stprintf_s(chemin, _countof(chemin), TEXT("%s\\%s"), pouchindir_prog, fd.cFileName); + if (!DeleteFile(chemin)) + break; + } while (FindNextFile(hSearch, &fd)); + FindClose(hSearch); + } +} - if (!bMutexError || res == WAIT_ABANDONED) { - // Attente de 250ms (car si trop rapide, on n'efface pas les fichiers - Sleep(250); - // On ne quitte plus PTVM, car on a récupéré pour la mise à jour - bQuitte = false; +/** + * Recherche d'une instance existante de l'application. + * \retval \p true si cette instance existe, et que l'application doit quitter + * \note Effets de bord : + * - si l'application tourne déjà, restauration de sa fenêtre de travail au cas + * où elle serait minimisée + * - effacement de fichiers temporaires + **/ +bool CheckForExistingInstance() +{ + // Première chose à faire : + // Vérifier si une autre instance ne fonctionne pas déjà - // - // Regarde si un fichier dont le nom se finit par «_» existe dans le dossier actuel de PTVM - WIN32_FIND_DATA fd = {0}; // Pour rechercher les fichiers - TCHAR chemin[MAX_PATH]; // Dossier actuel + pattern pour la recherche de fichiers de mise à jour + HANDLE hMutex = CreateMutex(NULL, TRUE, szAppName); + bool bQuitte = true; // Indique qu'il faut quitter + bool bMutexError = (GetLastError()==ERROR_ALREADY_EXISTS); // Mutex déjà existant - strcpy_T(chemin, pouchindir_prog); - strcat_T(chemin, TEXT("*_")); - // On recherche - HANDLE hSearch = FindFirstFile(chemin, &fd); + // On attend 3 secondes la libération du mutex + // Pas plus longtemps, car si ce n'est pas une mise à jour, l'utilisateur l'a appelé 2 fois, + // et donc, si c'est plus long avant de réafficher la fenêtre principale, celui-ci + // risque de le rappeller une fois de plus + DWORD res = WaitForSingleObject(hMutex, 3*1000); - if (hSearch != INVALID_HANDLE_VALUE) { + if (!bMutexError || res == WAIT_ABANDONED) { + // Attente de 250ms (car si trop rapide, on n'efface pas les fichiers) + Sleep(250); + // On ne quitte plus PTVM, car on a récupéré pour la mise à jour + bQuitte = false; - // On efface les fichiers dont le nom se finit par « _ » - do { - _stprintf_s(chemin, _countof(chemin), TEXT("%s\\%s"), pouchindir_prog, fd.cFileName); - res = DeleteFile(chemin); - } while (FindNextFile(hSearch, &fd)); - FindClose(hSearch); - } - } - - if (bQuitte && bMutexError) { - // On quitte (pas de mise à jour, ou attente trop longue), mais on - // affiche la fenêtre de Pouchin TV Mod déjà lancée au premier plan - HWND hPouchintvmod = FindWindow(szAppName, TEXT("Pouchin TV Mod")); - if (hPouchintvmod) { - SendMessage(hPouchintvmod, WM_SYSCOMMAND, SC_RESTORE, NULL); - SetForegroundWindow(hPouchintvmod); - return 0; - } + // Efface les fichiers dont le nom se finit par « _ » dans le dossier actuel de PTVM + CleanTemporaryFiles(); + } + + if (bQuitte && bMutexError) { + // On quitte (pas de mise à jour, ou attente trop longue), mais on + // affiche la fenêtre de Pouchin TV Mod déjà lancée au premier plan + HWND hPouchintvmod = FindWindow(szAppName, TEXT("Pouchin TV Mod")); + if (hPouchintvmod) { + SendMessage(hPouchintvmod, WM_SYSCOMMAND, SC_RESTORE, NULL); + SetForegroundWindow(hPouchintvmod); + return true; } } + return false; +} - MSG msg; - WNDCLASS wndclass; - HWND hWnd; - - CmdOptions * cmdOptions = TraiteCmdLine(); // Décodage des options - - hAppInstance = hInstance; - - // On lit la config maintenant, besoin des coords de la fenetre - load_config(); - +/// Initialisation de l'instance d'application +/// \retval \p true si succès +bool InitInstance() +{ // Chargement des icônes du programme : hPrgIcon = LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_PROG_ICON)); // Icône normale hRecIcon = LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_ICON_REC)); // Icône d'enregistrement - INITCOMMONCONTROLSEX icc={sizeof(INITCOMMONCONTROLSEX), ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_DATE_CLASSES}; + INITCOMMONCONTROLSEX icc = { + sizeof(INITCOMMONCONTROLSEX), + ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_DATE_CLASSES + }; + InitCommonControlsEx(&icc); // Register the frame class - wndclass.style = CS_DBLCLKS; - wndclass.lpfnWndProc = MainWndProc; - wndclass.cbClsExtra = 0; - wndclass.cbWndExtra = 0; - wndclass.hInstance = hInstance; - wndclass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_PROG_ICON)); - wndclass.hCursor = LoadCursor (NULL,IDC_ARROW); - wndclass.hbrBackground = CreateSolidBrush(colorKey);//(HBRUSH)(COLOR_WINDOW+1); - wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MAIN_MENU); - wndclass.lpszClassName = szAppName; + WNDCLASS wndclass = { + CS_DBLCLKS, // style + MainWndProc, // lpfnWndProc + 0, 0, // cbClsExtra, cbWndExtra + hAppInstance, // hInstance + LoadIcon(hAppInstance, MAKEINTRESOURCE(IDI_PROG_ICON)), // hIcon + LoadCursor(NULL, IDC_ARROW), // hCursor + CreateSolidBrush(colorKey), // hbrBackground + MAKEINTRESOURCE(IDR_MAIN_MENU), // lpszMenuName + szAppName // lpszClassName + }; - if (!RegisterClass(&wndclass)) return 0; -#if USE_CONSOLE==1 - startConsoleWin(true); -#endif // #if USE_CONSOLE==1 -#if USE_CONSOLE - // Affiche divers renseignements pour le debogguage - myprintf(TEXT("Compile le : %") A2t TEXT(" %") A2t TEXT("\n"), __DATE__, __TIME__); - myprintf(TEXT("Version : ") TEXT(PTVM_VERSION_STR) TEXT(" (") - #ifdef _UNICODE - TEXT("Unicode") - #else - TEXT("SBCS") - #endif - TEXT("), ") -#ifdef _WIN64 - TEXT("x64") -#else - TEXT("Win32") -#endif - TEXT("\n")); + if (RegisterClass(&wndclass)==0) + return false; - myprintf(TEXT("Tuner : %s\nRécepteur : %s\nMPEG2 : %s\nAudio : %s\nAC3 : %s\nVille : %s\n"), - nom_tuner, - nom_receiver, - filtreMPEG2, - filtreAudio, - filtreAc3, - nomVille); - myprintf(TEXT("Ligne de commande : [%s]\n"), GetCommandLine()); -#endif // #if USE_CONSOLE - // Vérifie l'existence du fichier "canaux.ini", et le crée à partir des ressources // s'il n'existe pas : cree_fichier_scan(); @@ -2414,29 +2415,49 @@ ZeroMemory(&windows_version, sizeof(windows_version)); windows_version.dwOSVersionInfoSize = sizeof(windows_version); if (GetVersionEx((OSVERSIONINFO *)&windows_version)) { - if (windows_version.dwMajorVersion >= 6) { - is_vista = true; + is_vista = windows_version.dwMajorVersion >= 6; + myprintf(is_vista ? + TEXT("Fonctionne sous Vista ou 2008 Serveur ou plus récent\t") : + TEXT("Fonctionne sous 2000 ou XP\t")); + } else + myprintf(TEXT("Erreur lors de la récupération de la version de Windows\t")); - // Sous Vista, on n'utilise l'OSD qu'avec le VMR9 - if (vmr_mode==vmt_VMR7_renderless || vmr_mode==vmt_VMR7_windowless) - use_osd = false; - - myprintf(TEXT("Fonctionne sous Vista ou 2008 Serveur ou plus récent\t")); - } else { - myprintf(TEXT("Fonctionne sous 2000 ou XP\t")); - } - } else { - myprintf(TEXT("Erreur lors de la récupération de la version de Windows\t")); - } myprintf(TEXT("\n##########\n\n")); HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); if (FAILED(hr)) { - affiche_erreurs(TEXT("Impossible d'initialiser la bibliothèque COM.")); - return hr; + affiche_erreurs(TEXT("Impossible d'initialiser la bibliothèque COM."), hr); + return false; } - hWnd = CreateWindowEx(0, + return true; +} + +/// Nettoyage de l'instance d'application +void CleanInstance() +{ + // Destruction de l'icône du programme (nécessaire ?) : + if (hPrgIcon != NULL) { + DestroyIcon(hPrgIcon); + hPrgIcon = NULL; + } + + // Destruction de l'icône d'enregistrement (nécessaire ?) : + if (hRecIcon != NULL) { + DestroyIcon(hRecIcon); + hRecIcon = NULL; + } + + // On efface la liste des raccourcis + DestroyAcceleratorTable(hMainAccel); + + // On libère toutes les ressources initialisées + CoUninitialize(); +} + +bool CreateMainWindow(int nCmdShow, bool bMinimize) +{ + HWND hWnd = CreateWindowEx(0, szAppName, TEXT("Pouchin TV Mod"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, @@ -2446,18 +2467,42 @@ winPos.H, NULL, NULL, - hInstance, + hAppInstance, NULL); // make sure window was created - if (!hWnd) { - CoUninitialize(); - return 0; + if (!hWnd) + return false; + + // show and update main window + if (bMinimize) { + ShowWindow(hWnd, SW_MINIMIZE); + UpdateWindow(hWnd); + if (minimize_system_tray) + ShowWindow(hWnd, SW_HIDE); + } else { + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); } - if (use_osd) - pOSD = new COsdAllObjects(); + hMainMenu = GetMenu(hWnd); + return true; +} +/** + * Traitement principal de l'application. + * Cette fonction regroupe toutes les fonctionnalités dépendantes de la configuration, + * qui sont susceptibles d'être relancées après une modification de celle-ci. + * \param[in] cmdOptions Options de ligne de commande. Peut être \p NULL. + * \param[in] nCmdShow État de la fenêtre au démarrage + * \retval Code retour ; si != 0, l'application doit être quittée en retournant cette valeur. + **/ +int MainTask(CmdOptions * cmdOptions) +{ + // Sous Vista, on n'utilise l'OSD qu'avec le VMR9 + if (is_vista && (vmr_mode==vmt_VMR7_renderless || vmr_mode==vmt_VMR7_windowless)) + use_osd = false; + // On vérifie si les répertoires spécifiés pour l'enregistrement sont valides ou non : verifie_repertoire_captures(video_dir, _countof(video_dir), CSIDL_MYVIDEO /* = Répertoire "Mes vidéos" */, TEXT("enregistrements des vidéos")); @@ -2467,53 +2512,44 @@ // Si on minimise dans la zone système, n'affiche pas la fenêtre dans la barre des tâches update_systray_state(); - // Comme marqué, on crée la barre de status de la fenêtre - create_status_bar(); + // Comme marqué, on crée la barre d'état ("status") de la fenêtre + if (hMainStatus == NULL) + create_status_bar(); + update_status_size(); + update_status_bar(); - // Lecture du fichier des chaînes (avant celle de la programmation, car on peut avoir besoin de la liste - // des chaînes dans celle-ci). - lit_chaines(); - - // Chargement et purge de la liste des programmes - init_programmation(); - // Rétablissement de la priorité de traitement sauvée dans la configuration : set_priority(configPriority); + // Ignorer la sauvegarde de l'état minimisé (vérifier si c'est adéquat) + if (configState == etf_minimized) + configState = etf_normal; + // Ajustements de l'état de départ de la fenêtre : if (Canaux.size()==0) { // Pas question d'utiliser un état de fenêtre sauvegardé dans la config // ou de tourner en mode minimisé si aucune chaîne n'a encore été détectée - cmdOptions->bMinimize = false; + if (cmdOptions) + cmdOptions->bMinimize = false; configState = etf_normal; - } else if (cmdOptions->bMinimize) { - configState = etf_minimized; - } else if (cmdOptions->bFs){ - configState = etf_fullscreen; - } else if (cmdOptions->bMax){ - configState = etf_maximized; - } else if (cmdOptions->bNoborder){ - configState = etf_noborders; - } else if (cmdOptions->bNormal) { - configState = etf_normal; - } else if (configState == etf_minimized) { - // Ignorer la sauvegarde de l'état minimisé (vérifier si c'est adéquat) - configState = etf_normal; } - // show and update main window - if (cmdOptions->bMinimize) { - ShowWindow(hWnd, SW_MINIMIZE); - UpdateWindow(hWnd); - if (minimize_system_tray) - ShowWindow(hWnd, SW_HIDE); - } else { - ShowWindow(hWnd, nCmdShow); - UpdateWindow(hWnd); + if (cmdOptions) { + if (cmdOptions->bMinimize) + configState = etf_minimized; + else if (cmdOptions->bFs) + configState = etf_fullscreen; + else if (cmdOptions->bMax) + configState = etf_maximized; + else if (cmdOptions->bNoborder) + configState = etf_noborders; + else if (cmdOptions->bNormal) + configState = etf_normal; } bool config_ok = check_config() && GetKeyState(VK_SHIFT)>=0; + for (;;) { if (!config_ok) { if (drivers_dialog()!=IDOK) { @@ -2525,7 +2561,10 @@ continue; } } - if (SUCCEEDED(hr = build_graph())) { + + HRESULT hr = build_graph(); + + if (SUCCEEDED(hr)) { if (Canaux.size()> 0 || scan_dialog()==IDOK) { config_ok = true; break; // tout est ok, on passe à la suite @@ -2539,22 +2578,36 @@ // Appeler une nouvelle fois, car certains filtres trouvent très malin d'appeler // CoUninitialize pour se protéger des usages non autorisés : - CoInitializeEx(NULL,COINIT_MULTITHREADED); + CoInitializeEx(NULL, COINIT_MULTITHREADED); } if (!do_init_vmr()) return -1; + if (cmdOptions && cmdOptions->nChaine > 0) { + // Un numéro de chaîne passé en paramètre est prioritaire sur la chaîne + // courante sauvegardée dans la configuration + + // Vérifie que la chaîne passée en paramètre est connue + int ixChaine = trouve_chaine_par_no((WORD)cmdOptions->nChaine); + + if (ixChaine_ok(ixChaine)) + sidChaineConfig = Canaux[ixChaine].SID; + } + restaure_chaine(sidChaineConfig); set_volume(volumeCourant); - if (cmdOptions->bMinimize) { + if (cmdOptions && cmdOptions->bMinimize) { // On a lancé avec le paramètre demandant de masquer la fenêtre - if(!suspend_minimized && !rebranche(true)) - return -1; + if(!suspend_minimized) { + myprintf(TEXT("rebranche\n")); + if (!rebranche(true)) + return -1; + } } else { - if (ixChaine_ok(ixChaineCourante)) { + if (verif_freq_demarrage && ixChaine_ok(ixChaineCourante)) { int nbChaines = (int)Canaux.size(); long freq_courante = Canaux[ixChaineCourante].khz; int ixChaineSauve = ixChaineCourante; @@ -2565,39 +2618,26 @@ long new_freq = Canaux[i].khz; if (new_freq != freq_courante) { - change_chaine(Canaux[i].numeroChaine); + UINT16 nChaine = Canaux[i].numeroChaine; + + myprintf(TEXT("change_chaine(%u)\n"), nChaine); + change_chaine(nChaine); break; // Un seul changement de fréquence requis } } + + myprintf(TEXT("change_chaine(%u)\n"), ixChaineSauve); change_chaine(ixChaineSauve); } + myprintf(TEXT("rebranche\n")); + // Branchement initial des sorties audio et vidéo : if (!rebranche(true)) return -1; } - if ((cmdOptions->nChaine > 0) && (cmdOptions->nChaine <= (int)Canaux.size())){ - // Vérifie que la chaîne passée en paramètre est connue - int temp = trouve_chaine_par_no((WORD)cmdOptions->nChaine); - if (temp != -1) - zappe_index(temp); - } - if (cmdOptions->bRecPS) { - if (start_record_ts(ixChaineCourante)>=0){ - update_record_menus(hMainWnd); - } - } - - if (cmdOptions->bRecTS) { - if (start_record_ps(ixChaineCourante,ixSonCourant)>=0){ - update_record_menus(hMainWnd); - } - } - - hMainMenu = GetMenu(hWnd); - - // On met à jour les raccourci définis par l'utilisateur + // On met à jour les raccourcis définis par l'utilisateur update_shortcuts_menus(); /* @@ -2612,13 +2652,29 @@ niData.update_state(); - // On n'a plus besoin des options de la ligne de commande, on libère donc la mémoire - delete [] cmdOptions; - // Définir le timer avant l'enregistrement suivant, // éventuellement débutant immédiatement si intervalle en cours : set_timer_record(); + // Traiter les enregistrements demandés par ligne de commande : + if (cmdOptions) { + if (cmdOptions->bRecPS) { + if (start_record_ts(ixChaineCourante)>=0){ + update_record_menus(hMainWnd); + } + } + + if (cmdOptions->bRecTS) { + if (start_record_ps(ixChaineCourante, ixSonCourant)>=0){ + update_record_menus(hMainWnd); + } + } + } + + myprintf(TEXT("Entrée dans la boucle de messages\n")); + + MSG msg; + // boucle qui traite les messages clavier while(GetMessage(&msg, NULL, 0, 0) ) { if (hSignalDlg!=NULL && IsDialogMessage(hSignalDlg, &msg)) @@ -2627,16 +2683,24 @@ continue; if (is_record_dialog_message(msg)) continue; - if (TranslateAccelerator(hWnd, hMainAccel, &msg)) + if (TranslateAccelerator(hMainWnd, hMainAccel, &msg)) continue; TranslateMessage(&msg); DispatchMessage(&msg); } - // Destruction des objets OSD : - if (pOSD) - delete pOSD; + // Je mets ceci (temporairement ... ??) à cause d'un problème que je rencontre parfois, + // où on voit PouchinTV quitter tout en restant comme "zombie", + // mais consommant toutes les ressources, dans le système. + // Au moins ainsi ça devrait éviter de bloquer l'ordinateur + // si le programme tournait en priorité élevée. + // À virer quand ce problème aura été résolu, donc. - Gingko + set_priority(IDLE_PRIORITY_CLASS); + clean_dshow(); + + niData.disable(); + // Si on demandé la mise à jour de MSN, on retire le titre modifié if (use_msn) { // On cherche la fenêtre @@ -2649,28 +2713,91 @@ msndata.dwData = 0x547; msndata.lpData = TEXT("\\0Music\\00\\0\\0\\0\\0\\0\\0"); msndata.cbData = (lstrlen((TCHAR *) msndata.lpData)+1)*sizeof(TCHAR); - SendMessage(msnui, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&msndata); + SendMessage(msnui, WM_COPYDATA, (WPARAM)hMainWnd, (LPARAM)&msndata); } } - // Destruction de l'icône du programme (nécessaire ?) : - if (hPrgIcon != NULL) { - DestroyIcon(hPrgIcon); - hPrgIcon = NULL; - } + return (int)msg.wParam; +} - // Destruction de l'icône d'enregistrement (nécessaire ?) : - if (hRecIcon != NULL) { - DestroyIcon(hRecIcon); - hRecIcon = NULL; - } +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + hAppInstance = hInstance; - // On efface la liste des raccourcis - DestroyAcceleratorTable(hMainAccel); + // Définition des répertoires de base de l'application + ini_app_paths(); - // On libère toutes les ressources initialisées - CoUninitialize(); + // Première chose à faire : + // Vérifier si une autre instance ne fonctionne pas déjà + if (CheckForExistingInstance()) + return 0; + // On lit la config maintenant, besoin des coords de la fenêtre (surtout si la console + // de debugging est présente) + load_config(); + +#if USE_CONSOLE + // Affichage des messages de debugging initiaux, avec ouverture éventuelle de la console + #if USE_CONSOLE==1 + startConsoleWin(true); + #endif // #if USE_CONSOLE==1 + // Affiche divers renseignements pour le debogguage + myprintf(TEXT("Compile le : %") A2t TEXT(" %") A2t TEXT("\n"), __DATE__, __TIME__); + myprintf(TEXT("Version : ") TEXT(PTVM_VERSION_STR) TEXT(" (") + #ifdef _UNICODE + TEXT("Unicode") + #else + TEXT("SBCS") + #endif + TEXT("), ") + #ifdef _WIN64 + TEXT("x64") + #else + TEXT("Win32") + #endif + TEXT("\n")); + + myprintf(TEXT("Tuner : %s\nRécepteur : %s\nMPEG2 : %s\nAudio : %s\nAC3 : %s\nVille : %s\n"), + nom_tuner, + nom_receiver, + filtreMPEG2, + filtreAudio, + filtreAc3, + nomVille); + myprintf(TEXT("Ligne de commande : [%s]\n"), GetCommandLine()); +#endif // #if USE_CONSOLE + + // Décodage des options + CmdOptions * cmdOptions = TraiteCmdLine(); + + // Initialisations d'instance d'application + if (!InitInstance()) + return -1; + + // Lecture du fichier des chaînes (avant celle de la programmation, car on peut avoir + // besoin de la liste des chaînes dans celle-ci). + lit_chaines(); + + // Chargement et purge de la liste des programmes + init_programmation(); + + if (!CreateMainWindow(nCmdShow, cmdOptions && cmdOptions->bMinimize)) + return -1; + + int nRetCode; + + do { + bNeedRestart = false; + + nRetCode = MainTask(cmdOptions); + + // On n'a plus besoin des options de la ligne de commande, on libère donc la mémoire + delete [] cmdOptions; + cmdOptions = NULL; // Pas d'options en cas de redémarrage du programme + } while (bNeedRestart); + + CleanInstance(); + if (shutdown_on_quit) { if (!shutdown()) { myprintf(TEXT("Impossible d'arrêter l'ordinateur")); @@ -2679,5 +2806,5 @@ // Pour témoigner qu'on est bien passés par ici en quittant : myprintf(TEXT("On quitte !\n")); - return (int)msg.wParam; + return nRetCode; } Modifié: trunk/main.h =================================================================== --- trunk/main.h 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/main.h 2009-01-17 19:16:15 UTC (rev 168) @@ -31,8 +31,6 @@ extern TCHAR szAppName[]; //!< Nom de l'application (pour le titre de la fenêtre) -extern WORD sidChaineConfig; //!< SID chaîne récupéré dans 'config.ini' - extern HINSTANCE hAppInstance; //!< Handle d'instance de l'application extern HWND hMainWnd; //!< Handle de la fenêtre principale de l'application extern HWND hMainStatus; //!< Handle de la barre d'état de l'application @@ -43,6 +41,7 @@ extern HICON hRecIcon; //!< Icône utilisée en mode enregistrement extern bool is_vista; //!< \p true si on est sous Windows Vista +extern bool bNeedRestart; //!< \p true si l'application doit être relancée /// diverses informations sur la version de windows (utile plus tard ?) extern OSVERSIONINFOEX windows_version; @@ -75,7 +74,8 @@ #define WM_APP_HOOK_OK (WM_APP+6) #define WM_APP_HOOK_CANCEL (WM_APP+7) #define WM_APP_GRAPHNOTIFY (WM_APP+8) -#define WM_VIDEO_SIZE_CHANGED (WM_APP+9) +#define WM_APP_VIDEOSIZE_CHG (WM_APP+9) +#define WM_APP_RESTART (WM_APP+10) /** @} */ // fin de WM_APP_codes /** Modifié: trunk/rendering.cpp =================================================================== --- trunk/rendering.cpp 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/rendering.cpp 2009-01-17 19:16:15 UTC (rev 168) @@ -372,6 +372,8 @@ /// Affichage du nom de la chaîne et du nom de l'émission en cours /// param[in] canal Descripteur de la chaîne courante +/// \todo Vérifier que l'émission en cours est bien disponible (au démarrage, il arrive +/// que l'émission suivante soit chargée en premier et soit temporairement seule disponible) void COsdAllObjects::DisplayChannelInfo(const Chaine & canal) { cTopRight.SetText(TEXT("%") A2t, canal.nom); @@ -583,6 +585,26 @@ pOSD->DoPaint(hDC); } +void CVideoMixingRenderer::UpdateVideoPos() +{ + DWORD tick = GetTickCount(); + DWORD elapsed = tick-last_tick; + + if (elapsed < DUREE_VIDEO_MOVE) { + // Le dernier appel à cette fonction est vieux de moins que DUREE_VIDEO_MOVE : + // On ne fait rien, et on programme un timer pour rappeler la même fonction + // lorsque ce délai sera écoulé. + SetTimer(hMainWnd, TIMER_VIDEO_MOVE, DUREE_VIDEO_MOVE-elapsed, NULL); + return; + } + last_tick = tick; + + // Calcule le rectangle de la vidéo : + RECT sRect = PlaceVideoInRect(CalcCliRect()); + + SetVideoPosition(&sRect, video_pan_mode==pm_Stretch); +} + // ==================================================================================== // Déclaration de la classe CNullVideoRenderer // ==================================================================================== @@ -1434,6 +1456,9 @@ **/ HRESULT init_vmr() { + if (use_osd && !pOSD) + pOSD = new COsdAllObjects(); + HRESULT hr = S_OK; if (!pVMR) { // si pas déjà initialisé @@ -1476,6 +1501,23 @@ } /** + * Nettoyage du VMR et de l'OSD + **/ +void clean_vmr() +{ + if (pVMR) { + delete pVMR; + pVMR = NULL; + } + + // Destruction des objets OSD : + if (pOSD) { + delete pOSD; + pOSD = NULL; + } +} + +/** * Mise à jour des coordonnées de l'écran (à appeler en réponse à tout événement * de nature à modifier les dimensions de la vidéo) **/ @@ -1484,25 +1526,8 @@ if (pOSD) pOSD->UpdateRectsAndFont(); - if (pVMR) { - static DWORD last_tick = 0; - DWORD tick = GetTickCount(); - DWORD elapsed = tick-last_tick; - - if (elapsed < DUREE_VIDEO_MOVE) { - // Le dernier appel à cette fonction est vieux de moins que DUREE_VIDEO_MOVE : - // On ne fait rien, et on programme un timer pour rappeler la même fonction - // lorsque ce délai sera écoulé. - SetTimer(hMainWnd, TIMER_VIDEO_MOVE, DUREE_VIDEO_MOVE-elapsed, NULL); - return; - } - last_tick = tick; - - // Calcule le rectangle de la vidéo : - RECT sRect = PlaceVideoInRect(CalcCliRect()); - - pVMR->SetVideoPosition(&sRect, video_pan_mode==pm_Stretch); - } + if (pVMR) + pVMR->UpdateVideoPos(); } // ==================================================================================== Modifié: trunk/rendering.h =================================================================== --- trunk/rendering.h 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/rendering.h 2009-01-17 19:16:15 UTC (rev 168) @@ -61,6 +61,7 @@ class CVideoMixingRenderer : public CComPtr { CComPtr pInputPin; //!< Interface sur la broche d'entrée + DWORD last_tick; protected: /// Création et ajout du VMR dans le filtre virtual HRESULT CreateAndAdd() = 0; @@ -87,7 +88,8 @@ public: /// Constructeur - CVideoMixingRenderer() + CVideoMixingRenderer() : + last_tick(0) {} /// Définition du mode de ratio d'aspect. @@ -153,6 +155,11 @@ /// Appel sur notification de redimensionnement de la fenêtre virtual void Resize() {} + /// Repositionnement de la vidéo après changement dans les paramètres, + /// avec une temporisation pour assurer que le changement n'intervient + /// pas plus souvent que tous les #DUREE_VIDEO_MOVE. + void UpdateVideoPos(); + /// Destructeur virtual ~CVideoMixingRenderer() {} }; @@ -365,6 +372,7 @@ cBotRight(*this), cBotLeft(*this) { + ZeroMemory(&sOsdRect, sizeof(sOsdRect)); UpdateRectsAndFont(); } @@ -449,6 +457,11 @@ HRESULT init_vmr(); /** + * Nettoyage du VMR et de l'OSD + **/ +void clean_vmr(); + +/** * Mise à jour des coordonnées de l'écran (à appeler en réponse à tout événement * de nature à modifier les dimensions de la vidéo) **/ Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/res.rc 2009-01-17 19:16:15 UTC (rev 168) @@ -169,10 +169,13 @@ CAPTION "Options" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN - GROUPBOX "Mode minimisé",IDC_STATIC,7,7,276,50 - CONTROL "Suspendre si minimisé",IDC_SUSPEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,20,262,10 + GROUPBOX "Mode minimisé",IDC_STATIC,7,7,136,50 + CONTROL "Suspendre si minimisé",IDC_SUSPEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,20,124,10 CONTROL "Minimiser dans la zone de notification",IDC_SYSTEM_TRAY, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,37,262,10 + "Button",BS_AUTOCHECKBOX | BS_VCENTER | BS_MULTILINE | WS_TABSTOP,14,34,124,16 + GROUPBOX "Initialisation",IDC_STATIC,147,7,136,50 + CONTROL "Faire un changement de fréquence, au démarrage, pour pallier un bug de certains tuners",IDC_VERIF_FREQ_START, + "Button",BS_AUTOCHECKBOX | BS_VCENTER | BS_MULTILINE | WS_TABSTOP,154,20,124,24 GROUPBOX "Audio",IDC_STATIC,7,62,276,30 CONTROL "Utiliser l'AC3 par défaut",IDC_AC3_DEF,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,75,262,10 GROUPBOX "Vidéo",IDC_STATIC,7,98,276,36 Modifié: trunk/resource.h =================================================================== --- trunk/resource.h 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/resource.h 2009-01-17 19:16:15 UTC (rev 168) @@ -74,6 +74,7 @@ #define IDC_NAME 1048 #define IDC_RECORD 1049 #define IDC_INACTIVE 1050 +#define IDC_VERIF_FREQ_START 1051 #define IDC_METHOD 1052 #define IDC_AUDIO 1053 #define IDC_AUDIO_EPG 1057 Modifié: trunk/settings.cpp =================================================================== --- trunk/settings.cpp 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/settings.cpp 2009-01-17 19:16:15 UTC (rev 168) @@ -256,12 +256,12 @@ /** * Affiche la fenêtre de dialogue de renumérotation des chaînes **/ -static BYTE renumber_dialog() +static UINT16 renumber_dialog() { INT_PTR res = DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_RENUMBER), hMainWnd, RenumberDialogProc, DIALOGMODE); - return BYTE(res); + return UINT16(res); } /** @} */ @@ -1250,7 +1250,7 @@ case _cmd_(IDOK, BN_CLICKED): // sauvegarder le changement drivers_apply(hDlg); - // ... passage à travers + // // ... (passage à travers) case _cmd_(IDCANCEL, BN_CLICKED): EndDialog(hDlg, LOWORD(wParam)); @@ -1261,12 +1261,8 @@ case WM_NOTIFY: switch (_ncode_(lParam)) { case PSN_APPLY: // Application des changements - if (drivers_apply(hDlg)) { - MessageBox(hMainWnd, - TEXT("Les modifications apportées à la configuration matérielle ou bien\n") - TEXT("aux codecs utilisés s'appliqueront après redémarrage de l'application."), - TEXT("Paramètres modifiés"), MB_ICONINFORMATION); - } + if (drivers_apply(hDlg)) + bNeedRestart = true; return psn_result(hDlg, PSNRET_NOERROR); } return FALSE; @@ -2102,7 +2098,7 @@ } } } else if (p->hdr.code == LVN_ENDSCROLL) { - // On a déscendu le scroll + // On a descendu le scroll NMLVSCROLL *scroll = (NMLVSCROLL*)lParam; dx += scroll->dx; dy += scroll->dy; @@ -2272,6 +2268,7 @@ set_check(hDlg, IDC_USE_OSD, use_osd); set_check(hDlg, IDC_MSN, use_msn); + set_check(hDlg, IDC_VERIF_FREQ_START, verif_freq_demarrage); set_check(hDlg, IDC_ALLOW_STREAM_RECORD, allow_stream_record); return TRUE; @@ -2305,17 +2302,14 @@ vmr_mode = GetVMRSel(hDlg); use_osd = get_check(hDlg, IDC_USE_OSD); use_msn = get_check(hDlg, IDC_MSN); + verif_freq_demarrage = get_check(hDlg, IDC_VERIF_FREQ_START); allow_stream_record = get_check(hDlg, IDC_ALLOW_STREAM_RECORD); niData.update_state(); // Avertir de la nécessité de relancer l'application si un des paramètres // de sortie vidéo a été modifié : - if (vmr_mode!=old_vmr_mode || use_osd!=old_use_osd) { - MessageBox(hMainWnd, - TEXT("Les modifications apportées à la configuration de la sortie\n") - TEXT("vidéo s'appliqueront après redémarrage de l'application."), - TEXT("Paramètres modifiés"), MB_ICONINFORMATION); - } + if (vmr_mode!=old_vmr_mode || use_osd!=old_use_osd) + bNeedRestart = true; return psn_result(hDlg, PSNRET_NOERROR); } } return FALSE; Modifié: trunk/update.h =================================================================== --- trunk/update.h 2009-01-17 02:17:13 UTC (rev 167) +++ trunk/update.h 2009-01-17 19:16:15 UTC (rev 168) @@ -27,5 +27,8 @@ * Traitement de la mise à jour par Internet * * \param[in] hOwner handle de la fenêtre parente + * \todo Désactiver la mise à jour lorsque l'utilisateur n'utilise pas un compte + * administrateur, ou bien produire un avertissement genre "Vous devez être + * administrateur de l'ordinateur pour pouvoir utiliser cette fonction". **/ void do_web_update(HWND hOwner); From pouchintv-dev at baysse.fr Thu Jan 22 16:08:46 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Thu, 22 Jan 2009 16:08:46 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r169 - trunk Message-ID: <20090122150846.6984A5F41F@mail.baysse.fr> Author: gingko Date: 2009-01-22 16:08:46 +0100 (jeu, 22 jan 2009) New Revision: 169 Modified: trunk/base.h trunk/channels.cpp trunk/epg.cpp trunk/graph.cpp trunk/graph.h trunk/ini.cpp trunk/ini.h trunk/main.cpp trunk/recprog.cpp trunk/res.rc trunk/resource.h trunk/settings.cpp trunk/utils.cpp trunk/utils.h Log: EPG redimensionnable + quelques raccourcis clavier ajoutés. epg.cpp, res.rc : * La boîte de dialogue du Guide des Programmes est maintenant redimensionnable (réalisé d'après une modification proposée par 'rtah'). ini.h, ini.cpp, main.cpp, resource.h : * Ajout d'une commande accessible uniquement par raccourci clavier pour resyntoniser la même fréquence que celle couramment utilisée (Ctrl-F par défaut). Permet souvent de débloquer un graphe qui s'est figé (auparavant, il fallait changer deux fois de fréquence pour avoir le même résultat). * Ajout de 4 commandes accessibles uniquement par raccourcis clavier, et disponibles uniquement en mode debugging, pour démarrer, arrêter ou mettre en pause le graphe, ainsi que pour interroger l'état de celui-ci. Les codes par défaut sont Ctrl-R, Ctrl-Shift-R, Ctrl-Alt-R et R respectivement. settings.cpp, epg.cpp, regprog.cpp : * Dans les contrôles de dialogue présentant des listes, on peut maintenant réorganiser les colonnes (mais cette réorganisation n'est pas sauvegardée). res.rc : * Le contrôle listant les raccourcis ne doit pas avoir le style "LVS_EDITLABELS". main.cpp : * La fonction qui teste pour l'existence d'une instance déjà existante de PTVM en cours d'exécution n'en restaure plus la fenêtre si la seconde instance est lancée avec l'option "--minimize". * Ajout de l'attribut "static" à un grand nombre de fonctions à vocations strictement locales à ce module. utils.h, utils.cpp, settings.cpp : * La fonction "ListView_AjouteColonnes" et la structure "Tab_cols" sont déplacés ici, afin de permettre leur utilisation dans d'autres modules que "settings.cpp". epg.cpp, recprog.cpp : * Factorisation : utilisation de la fonction "ListView_AjouteColonnes" pour construire les listes d'EPG et d'enregistrements programmés. graph.h, graph.cpp : * Ajout de la fonction "graph_Pause", et de l'affichage (en mode debugging) de l'événement "EC_VMR_RENDERDEVICE_SET", qui semble revenir souvent. channels.cpp : * Amélioration de quelques instructions de logging "myprintf". Modifié: trunk/base.h =================================================================== --- trunk/base.h 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/base.h 2009-01-22 15:08:46 UTC (rev 169) @@ -137,8 +137,6 @@ // /////////////////////////////////////////////////////////////////// -#include "ini.h" - // Macros d'assistance à l'insertion conditionnelle de courtes séquences de code en mode debugging : // (utile en particulier s'il s'agit de paramètres supplémentaires de fonctions) #if USE_CONSOLE @@ -153,6 +151,8 @@ #define IF_DEBUG_WE(c1, c2) c2 ///< Code conditionnel exécuté selon compilation debug ou pas ("with else") #endif +#include "ini.h" // (a besoin de "IF_DEBUG_WE") + #if defined _M_IX86 #pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") #elif defined _M_IA64 Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/channels.cpp 2009-01-22 15:08:46 UTC (rev 169) @@ -186,7 +186,7 @@ // valeur par défaut, selon préférences globales de l'utilisateur : HRESULT Chaine::branche(bool reset_son) const { - myprintf(TEXT("SID %i, TSID %i, ONID %i, freq : %i\n"), SID, TSID, ONID, khz); + myprintf(TEXT("Branche SID=%i, TSID=%i, ONID=%i, freq=%i\n"), SID, TSID, ONID, khz); ULONG pid = video_pid; HRESULT hr = E_FAIL; // valeur par défaut @@ -461,13 +461,11 @@ } if (ixChaine >= 0) { - myprintf(TEXT("zappe %i\n"), ixChaine+1); - const Chaine & nouveau_canal = Canaux[ixChaine]; - myprintf(TEXT("zappe %i\n"), nouveau_canal.numeroChaine); - myprintf(TEXT("SID %i, TSID %i, ONID %i, freq : %i\n"), - nouveau_canal.SID, nouveau_canal.TSID, nouveau_canal.ONID, nouveau_canal.khz); + myprintf(TEXT("Zappe ix=%i, no=%i, SID=%i, TSID=%i, ONID=%i, freq=%i, nom=\"%") A2t TEXT("\"\n"), + ixChaine, nouveau_canal.numeroChaine, nouveau_canal.SID, nouveau_canal.TSID, + nouveau_canal.ONID, nouveau_canal.khz, nouveau_canal.nom); if (freq_differente) change_frequence(nouveau_canal.khz); Modifié: trunk/epg.cpp =================================================================== --- trunk/epg.cpp 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/epg.cpp 2009-01-22 15:08:46 UTC (rev 169) @@ -125,45 +125,76 @@ } /** - * Fonction gérant la boite de dialogue des programmes via l'EPG + * Déplacement d'un contrôle de dialogue sans modifier sa taille, + * en spécifiant la différence entre l'ancienne position et la nouvelle. + * \param[in] hDlg "Handle" du dialogue + * \param[in] nId Identifiant du contrôle + * \param[in] dx Déplacement horizontal + * \param[in] dy Déplacement vertical **/ +static void ChgCtlPos(HWND hDlg, INT nId, int dx, int dy) +{ + HWND hCtl = GetDlgItem(hDlg, nId); + RECT sRect; + + GetWindowRect(hCtl, &sRect); + + POINT sPt = {sRect.left+dx, sRect.top+dy}; + + ScreenToClient(hDlg, &sPt); + SetWindowPos(hCtl, 0, sPt.x, sPt.y, 0, 0, + SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER); + + // Le contrôle vient d'être redessiné, mais on l'invalide quand même, car il + // arrive que l'actualisation du contrôle voisin provoque une corruption sur + // les bords en cas de redimensionnement rapide : + InvalidateRect(hCtl, NULL, false); +} + +/** + * Redimensionnement d'un contrôle de dialogue sans modifier sa position, + * en spécifiant la différence entre l'ancienne taille et la nouvelle. + * \param[in] hDlg "Handle" du dialogue + * \param[in] nId Identifiant du contrôle + * \param[in] dx Différence de taille horizontale + * \param[in] dy Différence de taille verticale + **/ +static void ChgCtlSiz(HWND hDlg, INT nId, int dx, int dy) +{ + HWND hCtl = GetDlgItem(hDlg, nId); + RECT sRect; + + GetWindowRect(hCtl, &sRect); + SetWindowPos(hCtl, 0, 0, 0, RWdt(sRect)+dx, RHgt(sRect)+dy, + SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER); +} + +/** + * Fonction gérant la boîte de dialogue des programmes via l'EPG + * \todo Envisager sauvegarde de la dimension de cette boîte de dialogue, + * maintenant qu'elle est redimensionnable. + **/ INT_PTR CALLBACK EpgDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - static HWND hListItem = NULL; // Handle de la liste + static HWND hListItem = NULL; // Handle de la liste + static RECT sSavRect; // Mémorisation du rectangle client dans WM_GETMINMAXINFO et avant WM_SIZE switch (uMsg) { case WM_INITDIALOG: { hListItem = GetDlgItem(hDlg, IDC_LIST_EPG); - // // Initialise la liste (ajout de la grille, des colonnes, etc.) - ListView_SetExtendedListViewStyle(hListItem, - LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP); - static const struct Tab_cols { - LPCTSTR nom; - int taille; - } t_cols[] = { - {TEXT("Chaîne") , 90}, - {TEXT("Début") , 90}, - {TEXT("Fin") , 90}, - {TEXT("Nom du programme"), 220}, - {TEXT("Description") , 700} + static const Tab_cols t_cols[] = { + {TEXT("Chaîne"), 90}, + {TEXT("Début"), 90}, + {TEXT("Fin"), 90}, + {TEXT("Nom du programme"), 220}, + {TEXT("Description"), 700}, + {NULL, 0} // Terminateur }; - for (int i=0; i<_countof(t_cols); i++) { - const Tab_cols & col = t_cols[i]; - LVCOLUMN colonne = { - LVCF_TEXT|LVCF_WIDTH, // mask - 0, // fmt - col.taille, // cx - const_cast(col.nom) // pszText - // le reste à zéro (implicite) - }; - - ListView_InsertColumn(hListItem, i, &colonne); - } - + ListView_AjouteColonnes(hListItem, t_cols); remplit_table_epg(hListItem); remplit_liste_methodes(GetDlgItem(hDlg, IDC_METHOD_EPG)); remplit_liste_audio(GetDlgItem(hDlg, IDC_AUDIO_EPG)); @@ -187,6 +218,34 @@ return FALSE; } + case WM_GETMINMAXINFO: { + MINMAXINFO & sMinMax = *reinterpret_cast(lParam); + + // Mémoriser l'ancienne taille pour calcul du changement : + GetClientRect(hDlg, &sSavRect); + // Dimensions minimales acceptables : + sMinMax.ptMinTrackSize.x = 480; + sMinMax.ptMinTrackSize.y = 128; + return FALSE; } + + case WM_SIZE:{ + RECT sRect; + + GetClientRect(hDlg, &sRect); + + // Calcul de la différence entre l'ancienne et la nouvelle taille : + int dx = RWdt(sRect)-RWdt(sSavRect); + int dy = RHgt(sRect)-RHgt(sSavRect); + + // Déplacement ou redimensionnement des contrôles : + ChgCtlPos(hDlg, IDC_METHOD_EPG, 0, dy); + ChgCtlPos(hDlg, IDC_AUDIO_EPG, 0, dy); + ChgCtlPos(hDlg, IDC_RECORD, 0, dy); + ChgCtlPos(hDlg, IDC_UPDATE, dx, dy); + ChgCtlPos(hDlg, IDOK, dx, dy); + ChgCtlSiz(hDlg, IDC_LIST_EPG, dx, dy); + return TRUE; } + case WM_COMMAND: switch(LOWORD(wParam)) { Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/graph.cpp 2009-01-22 15:08:46 UTC (rev 169) @@ -753,6 +753,19 @@ } /** + * Mise en pause du graphe + * \return Code d'erreur DirectShow + **/ +HRESULT graph_Pause() +{ + CComQIPtr pControl(pGraph); + + if (!pControl) + return E_NOINTERFACE; + return pControl->Pause(); +} + +/** * Arrêt du graphe * \return Code d'erreur DirectShow **/ @@ -802,6 +815,7 @@ while (SUCCEEDED(pEvents->GetEvent(&evCode, ¶m1, ¶m2, 0))) { #if USE_CONSOLE myprintf(TEXT("Graph Event 0x%02x=EC_%") A2t TEXT(", %08x, %08x\n"), evCode, + evCode==EC_VMR_RENDERDEVICE_SET ? "VMR_RENDERDEVICE_SET" : // 0x53 EnumToString(evCode, "BASE\0" // 0x00 "COMPLETE\0" // 0x01 Modifié: trunk/graph.h =================================================================== --- trunk/graph.h 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/graph.h 2009-01-22 15:08:46 UTC (rev 169) @@ -49,6 +49,12 @@ HRESULT graph_Run(); /** + * Mise en pause du graphe + * \return Code d'erreur DirectShow + **/ +HRESULT graph_Pause(); + +/** * Arrêt du graphe * \return Code d'erreur DirectShow **/ Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/ini.cpp 2009-01-22 15:08:46 UTC (rev 169) @@ -54,11 +54,12 @@ * \li \a Alt : pareil avec la touche Alt * \li \a Touche : indique la touche devant être combinée avec, si besoin est, Maj, Ctrl et Alt **/ -ShortcutItem shortcuts[25] = { +ShortcutItem shortcuts[IF_DEBUG_WE(30, 26)] = { // Identifiant nom textuel nom dans la config maj ctrl alt touche // Changement de chaînes {IDM_CHAN_AUG, TEXT("Chaîne suivante"), TEXT("Chaîne suiv"), {false, false, false, VK_DOWN}}, {IDM_CHAN_DIM, TEXT("Chaîne précédente"), TEXT("Chaîne préc"), {false, false, false, VK_UP}}, + {IDM_CHAN_TUNE, TEXT("Forcer une resyntonisation"), TEXT("Chaîne Resyntoniser"),{false, true, false, TEXT('F')}}, // EPG {IDM_EPG, TEXT("Guide des programmes"), TEXT("EPG Guide progs"), {false, false, false, TEXT('G')}}, {IDM_SHOW_PROGRAMME, TEXT("Programme actuel"), TEXT("EPG Affiche prog"), {false, false, false, TEXT('I')}}, @@ -85,7 +86,12 @@ {IDM_ALLWDT, TEXT("Utiliser toute la largeur"), TEXT("Aff Pleine largeur"), {false, false, false, TEXT('W')}}, {IDM_ALLHGT, TEXT("Utiliser toute la hauteur"), TEXT("Aff Pleine hauteur"), {false, false, false, TEXT('H')}}, {IDM_ETIRER, TEXT("Étirer la vidéo"), TEXT("Aff Étirer"), {false, false, false, TEXT('E')}}, - +#ifdef _DEBUG + {IDM_RUN_GRAPH, TEXT("Mettre le graphe en marche"), TEXT("Debug GrapheMarche"), {false, true, false, TEXT('R')}}, + {IDM_PAUSE_GRAPH, TEXT("Mettre le graphe en pause"), TEXT("Debug GraphePause"), {false, true, true, TEXT('R')}}, + {IDM_STOP_GRAPH, TEXT("Arrêter le graphe"), TEXT("Debug GrapheArrêt"), {true, true, false, TEXT('R')}}, + {IDM_GRAPH_STATE, TEXT("Voir l'état du graphe"), TEXT("Debug ÉtatGraphe"), {false, false, false, TEXT('R')}}, +#endif {IDM_ABOUT, TEXT("Afficher la fenêtre des crédits"), NULL, {false, true, false, VK_F1}}, }; @@ -1180,7 +1186,8 @@ /** * Sauvegarde les raccourcis **/ -void save_config_raccourcis(void) { +void save_config_raccourcis(void) +{ for (size_t i=0; i<_countof(shortcuts); i++) { ShortcutItem &shortcut = shortcuts[i]; TCHAR cle[32], valeur[128]; @@ -1219,7 +1226,8 @@ /** * Sauvegarde tous les paramètres de configuration **/ -void save_config(void) { +void save_config(void) +{ save_config_str(ini_tuner, nom_tuner); save_config_str(ini_receiver, nom_receiver); @@ -1433,7 +1441,7 @@ } // - // Remplisage du tableau des accélérateurs + // Remplissage du tableau des accélérateurs // Raccourci standard accel[j].fVirt = FVIRTKEY; Modifié: trunk/ini.h =================================================================== --- trunk/ini.h 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/ini.h 2009-01-22 15:08:46 UTC (rev 169) @@ -428,5 +428,6 @@ /** * Liste des différents raccourcis + * \todo Éviter que la taille de cette liste doive être spécifiée ici. **/ -extern ShortcutItem shortcuts[25]; +extern ShortcutItem shortcuts[IF_DEBUG_WE(30, 26)]; Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/main.cpp 2009-01-22 15:08:46 UTC (rev 169) @@ -189,7 +189,7 @@ enabled ? MFS_ENABLED : MFS_DISABLED); } -void update_priority_menu(HMENU hMenu) +static void update_priority_menu(HMENU hMenu) { DWORD prio = get_priority(); @@ -275,7 +275,7 @@ * Trouve la position d'un item de menu référencé par son identifiant. * Retourne -1 si pas trouvé. **/ -int FindMenuItemPosition(HMENU hMenu, UINT uID) +static int FindMenuItemPosition(HMENU hMenu, UINT uID) { int nbItems = GetMenuItemCount(hMenu); @@ -287,7 +287,7 @@ return -1; } -void formate_menu_chaine_nom(int ixGrabber, LPCTSTR prefixe, LPTSTR pstr, size_t bufSize) +static void formate_menu_chaine_nom(int ixGrabber, LPCTSTR prefixe, LPTSTR pstr, size_t bufSize) { LPCSTR nom = enregistrements_actuels[ixGrabber].channelName(); @@ -519,7 +519,7 @@ * \retval -1 si on n'a rien trouvé * \return l'index dans le tableau des raccourcis si on a trouvé **/ -int update_shortcut_menu_associe(const UINT &id) +static int update_shortcut_menu_associe(const UINT &id) { for (int i=0; i<_countof(shortcuts); i++) { if (id == shortcuts[i].action) @@ -535,7 +535,8 @@ * * \param[in] hMenu handle du menu devant être analysé **/ -void update_shortcut_menu_recur(HMENU hMenu) { +static void update_shortcut_menu_recur(HMENU hMenu) +{ int nbMenus = GetMenuItemCount(hMenu); for (int i=0; ibMinimize)) return 0; // On lit la config maintenant, besoin des coords de la fenêtre (surtout si la console @@ -2767,9 +2814,6 @@ myprintf(TEXT("Ligne de commande : [%s]\n"), GetCommandLine()); #endif // #if USE_CONSOLE - // Décodage des options - CmdOptions * cmdOptions = TraiteCmdLine(); - // Initialisations d'instance d'application if (!InitInstance()) return -1; Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/recprog.cpp 2009-01-22 15:08:46 UTC (rev 169) @@ -30,7 +30,7 @@ #include "channels.h" #include "record.h" #include "main.h" -#include "ini.h" +#include "utils.h" // #include #include @@ -1048,7 +1048,6 @@ static INT_PTR CALLBACK RecordDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HWND hListItem = NULL; - int i; static int selection = -1; // Index de l'item couramment sélectionné si >= 0 static NomProg selProgNom = TEXT(""); // Nom de la sélection courante (pour pouvoir reconstituer celle-ci // après modification ou tri de la liste) @@ -1059,33 +1058,17 @@ selProgNom[0] = 0; hListItem = GetDlgItem(hDlg, IDC_LIST_PROGRAMMES); - ListView_SetExtendedListViewStyleEx(hListItem, - LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); - static const struct Tab_cols { - LPCTSTR nom; - int taille; - } t_cols[] = { - {TEXT("Nom"), 120}, - {TEXT("Chaîne"), 82}, - {TEXT("Début"), 128}, - {TEXT("Fin"), 48}, - {TEXT("État"), 68} + static const struct Tab_cols t_cols[] = { + {TEXT("Nom"), 120}, + {TEXT("Chaîne"), 82}, + {TEXT("Début"), 128}, + {TEXT("Fin"), 48}, + {TEXT("État"), 68}, + {NULL, 0} // Terminateur }; - for (i=0; i<_countof(t_cols); i++) { - const Tab_cols & col = t_cols[i]; - LVCOLUMN colonne = { - LVCF_TEXT|LVCF_WIDTH, // mask - 0, // fmt - col.taille, // cx - const_cast(col.nom) // pszText - // le reste à zéro (implicite) - }; - - ListView_InsertColumn(hListItem, i, &colonne); - } - + ListView_AjouteColonnes(hListItem, t_cols); remplit_liste_programmes(hListItem); remplit_liste_chaines(GetDlgItem(hDlg, IDC_CHANNEL)); // Chargement du combo de choix des chaînes remplit_liste_methodes(GetDlgItem(hDlg, IDC_METHOD)); Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/res.rc 2009-01-22 15:08:46 UTC (rev 169) @@ -255,7 +255,7 @@ END IDD_EPG DIALOGEX 0, 0, 569, 310 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Guide des programmes" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN @@ -396,7 +396,7 @@ CAPTION "Raccourcis" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - CONTROL "",IDC_SHORTCUT,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_EDITLABELS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,276,179 + CONTROL "",IDC_SHORTCUT,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,276,179 PUSHBUTTON "Par défaut...",IDC_SHORTCUT_REINIT,7,189,62,18 LTEXT "Double clic pour modifier le raccourci.\nClic droit pour avoir plus d'options.",IDC_STATIC,79,189,204,18 END Modifié: trunk/resource.h =================================================================== --- trunk/resource.h 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/resource.h 2009-01-22 15:08:46 UTC (rev 169) @@ -176,6 +176,7 @@ #define IDM_CHAINES 40061 #define IDM_SHORT_DEFAUT 40062 #define IDM_SHORT_EFFACER 40063 +#define IDM_CHAN_TUNE 40064 #define IDM_ETIRER 40066 #define IDM_UPDATE 40067 #define IDM_SHOW_PROGRAMME 40068 @@ -185,12 +186,17 @@ #define IDM_CHAN_RESTORNUM 40071 #define IDM_CHAN_RESTORNOM 40072 +#define IDM_GRAPH_STATE 40075 // debug +#define IDM_RUN_GRAPH 40076 // debug +#define IDM_PAUSE_GRAPH 40077 // debug +#define IDM_STOP_GRAPH 40078 // debug + // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 135 -#define _APS_NEXT_COMMAND_VALUE 40073 +#define _APS_NEXT_COMMAND_VALUE 40079 #define _APS_NEXT_CONTROL_VALUE 1122 #define _APS_NEXT_SYMED_VALUE 121 #endif Modifié: trunk/settings.cpp =================================================================== --- trunk/settings.cpp 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/settings.cpp 2009-01-22 15:08:46 UTC (rev 169) @@ -168,51 +168,6 @@ } } -/** - * Change le style de la liste - * - * \param[in] hwndLV handle de la liste à modifier - * \param[in] dwExStyle style à appliquer - **/ -inline void ListView_SetExStyle(HWND hwndLV, DWORD dwExStyle) -{ - ListView_SetExtendedListViewStyleEx(hwndLV, dwExStyle, dwExStyle); -} - -/** - * Structure servant à décrire les colonnes devant être ajoutées dans la liste - */ -struct Tab_cols { - LPCTSTR nom; ///< Texte affiché en nom de colonne - int taille; ///< Largeur initiale (en pixel) de la colonne -}; - -/** - * Affiche les bordures horizontales et verticales à la liste passée, et rajoute les colonnes - * - * \param[in] hList handle de la liste traitée - * \param[in] t_cols tableau décrivant les colonnes - **/ -void ListView_AjouteColonnes(HWND hList, const Tab_cols *t_cols) { - int i = 0; - ListView_SetExStyle(hList, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); - - // Ajoute les différentes colonnes - while( t_cols[i].nom != NULL || t_cols[i].taille != 0) { - const Tab_cols & col = t_cols[i]; - LVCOLUMN colonne = { - LVCF_TEXT|LVCF_WIDTH, // mask - 0, // fmt - col.taille, // cx - const_cast(col.nom) // pszText - // le reste à zéro (implicite) - }; - - ListView_InsertColumn(hList, i, &colonne); - i++; - } -} - // ==================================================================================== // Renumérotation des chaînes // ==================================================================================== Modifié: trunk/utils.cpp =================================================================== --- trunk/utils.cpp 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/utils.cpp 2009-01-22 15:08:46 UTC (rev 169) @@ -41,6 +41,7 @@ #include #include #include "utils.h" +#include /** * Version CHAR -> WCHAR (utilise \p MultiByteToWideChar). @@ -126,6 +127,44 @@ } /** + * Change le style de la liste + * + * \param[in] hwndLV handle de la liste à modifier + * \param[in] dwExStyle style à appliquer + **/ +inline void ListView_SetExStyle(HWND hwndLV, DWORD dwExStyle) +{ + ListView_SetExtendedListViewStyleEx(hwndLV, dwExStyle, dwExStyle); +} + +/** + * Affiche les bordures horizontales et verticales à la liste passée, et rajoute les colonnes + * + * \param[in] hList handle de la liste traitée + * \param[in] t_cols tableau décrivant les colonnes + **/ +void ListView_AjouteColonnes(HWND hList, const Tab_cols *t_cols) +{ + int i = 0; + ListView_SetExStyle(hList, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP); + + // Ajoute les différentes colonnes + while( t_cols[i].nom != NULL || t_cols[i].taille != 0) { + const Tab_cols & col = t_cols[i]; + LVCOLUMN colonne = { + LVCF_TEXT|LVCF_WIDTH, // mask + 0, // fmt + col.taille, // cx + const_cast(col.nom) // pszText + // le reste à zéro (implicite) + }; + + ListView_InsertColumn(hList, i, &colonne); + i++; + } +} + +/** * Trouver la valeur binaire associée à une chaîne de caractères fournie, * selon la table 'assocTable'. Si la chaîne ne se trouve pas dans la table, * alors la valeur 'bydefault' est retournée. Modifié: trunk/utils.h =================================================================== --- trunk/utils.h 2009-01-17 19:16:15 UTC (rev 168) +++ trunk/utils.h 2009-01-22 15:08:46 UTC (rev 169) @@ -454,6 +454,22 @@ }; /** + * Structure servant à décrire les colonnes devant être ajoutées dans la liste + */ +struct Tab_cols { + LPCTSTR nom; ///< Texte affiché en nom de colonne + int taille; ///< Largeur initiale (en pixel) de la colonne +}; + +/** + * Affiche les bordures horizontales et verticales à la liste passée, et rajoute les colonnes + * + * \param[in] hList handle de la liste traitée + * \param[in] t_cols tableau décrivant les colonnes + **/ +void ListView_AjouteColonnes(HWND hList, const Tab_cols *t_cols); + +/** * Élément de table d'association chaîne <--> valeur binaire. * Cette structure est destinée à faire partie d'une table dont le dernier élément * doit avoir ses deux valeurs à NULL et 0 respectivement. From pouchintv-dev at baysse.fr Fri Jan 30 22:00:14 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Fri, 30 Jan 2009 22:00:14 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r170 - trunk Message-ID: <20090130210014.9F1695F8DD@mail.baysse.fr> Author: gingko Date: 2009-01-30 22:00:14 +0100 (ven, 30 jan 2009) New Revision: 170 Modified: trunk/Doxyfile trunk/LCD.cpp trunk/LCD.h trunk/channels.cpp trunk/channels.h trunk/epg.cpp trunk/grabber.h trunk/graph.cpp trunk/ini.cpp trunk/ini.h trunk/main.cpp trunk/main.h trunk/mpeg2defs.h trunk/parse.cpp trunk/record.cpp trunk/record.h trunk/recprog.cpp trunk/recprog.h trunk/rendering.cpp trunk/rendering.h trunk/res.rc trunk/resource.h trunk/search.cpp trunk/search.h trunk/trayicon.cpp Log: Correction de bugs, ajouts mineurs, optimisations, documentation. channels.h, channels.cpp : * Création d'une fonction "branche_pid" pour gérer les connexions sur la sortie du démultiplexeur * Simplification de la fonction "debranche_son" * Optimisation de la fonction "debranche_tous_pids" * Ajout d'un argument "bForceTune" à la fonction "change_chaine" afin de forcer la resyntonisation même si la fréquence ne change pas. * Ajout de méthodes à la structure "Emission" * Ajout d'un membre "Chaine::getCurrentProgramName" pour récupérer le nom du programme courant, tout en vérifiant les horaires de ce programme par rapport à l'heure courante. epg.cpp, recprog.cpp, res.rc, resource.h : * La sauvegarde de la méthode d'enregistrement et de la piste audio préférée est maintenant assurée à tout instant, et pas seulement au démarrage d'un enregistrement. * Cette sauvegarde est mise en commun avec les items correspondants dans les enregistrements programmés (les valeurs changés dans un des deux dialogues sont répercutées dans l'autre, et vice-versa). * Quand on double-clique sur une ligne de programme, la chaîne n'est resélectionnée que si elle est différente de la précédente. recprog.cpp : * Le changement de chaîne au démarrage d'un enregistrement programmé est maintenant fait avec "zappe_index" (auparavant, certains éléments de la barre d'état n'étaient pas mis à jour dans cette situation). ini.h, ini.cpp : * Ajout des fonctions "load_driver_str" et "save_driver_str" pour assurer une gestion intelligente de la sauvegarde des noms de pilotes et de codecs. * Les pilotes en mode 64 bits sont sauvegardés sous une appellation différente, en raison du fait qu'ils diffèrent des pilotes 32 bits alors que les deux versions peuvent exister simultanéments dans un système 64 bits. * Les énumérations "MethodeEnregistrement" et "AudioMode" sont déplacés dans "ini.h", car maintenant elles sont utilisées pour sauvegarder les méthodes d'enregistrement. LCD.h, LCD.cpp, main.cpp : * Simplifications diverses, prenant en compte certaines des modifications faites dans "channels.h". main.h, main.cpp : * Correction d'une erreur dans l'affichage du nom de l'émission sous MSN, et utilisation de "Chaine::getCurrentProgramName" à cet effet. * Ajout d'une fonction "change_chaine_update", intermédiaire entre "zappe_index" et "change_chaine", pour changer de chaîne en mettant à jour les menus, mais sans produire d'affichage OSD. * Correction d'un bug dans le code "Force le changement de fréquence, sans quoi on a un écran noir au démarrage avec le tuner USB Toshiba PX1256E-1TVH". mpeg2defs.h : * Correction d'une erreur de "SI_EIT_time::operator ()" qui faisait que, dans la liste EPG, les émissions n'étaient pas toujours dans l'ordre chronologique au voisinage de minuit. * Modification du formatage de nombreuses méthodes "inline" (il apparaît préférable de ne pas avoir les accolades ouvrantes et fermantes de ces méthodes sur la même ligne, afin de pouvoir mieux tracer ces méthodes avec le debugger de Visual Studio). * Quelques ajouts mineurs. rendering.h, rendering.cpp : * Optimisation limitant le nombre de rafraîchissements inutiles lors de la mise à jour simultanée de plusieurs objets OSD. * L'affichage OSD du nom de l'émission utilise la nouvelle méthode "Chaine::getCurrentProgramName", pour contrôler la validité des horaires (et affiche "..." en cas d'absence de nom d'émission valide). trayicon.cpp : * L'affichage "tooltip" du nom de l'émission utilise la nouvelle méthode "Chaine::getCurrentProgramName", pour contrôler la validité des horaires. graph.cpp : * La table de debugging des événements du graphe est complétée. Dans de nombreux fichiers : * Nombreux commentaires ajoutés (surtout dans channels.h/cpp et record.h/cpp). * Ajustement de certains appels "myprintf" (debugging) pour produire des messages plus propres et plus complets. Modifié: trunk/Doxyfile =================================================================== --- trunk/Doxyfile 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/Doxyfile 2009-01-30 21:00:14 UTC (rev 170) @@ -1232,6 +1232,9 @@ # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = "C:/Program Files/Graphviz 2.21/bin" +# Attention : sur un OS 64 bits, ce répertoire devrait être le suivant : +# DOT_PATH = "C:/Program Files (x86)/Graphviz 2.21/bin" + # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). Modifié: trunk/LCD.cpp =================================================================== --- trunk/LCD.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/LCD.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -176,7 +176,7 @@ * \return toute autre erreur en cas d'échec **/ DWORD CLcd::ActualiseLcd() { - if (! this->m_initialise) + if (!m_initialise) return ERROR_NOT_CAPABLE; lgLcdBitmap160x43x1 bitmap; @@ -264,51 +264,29 @@ * \param[in] nomChaine Nom de la chaîne **/ void CLcd::SetChaine(const char *nomChaine){ - if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici + if (!m_initialise) + return; // Pas initialisé, donc, pas besoin de perdre du temps ici - strncpy_s(this->m_chaine, _countof(this->m_chaine), nomChaine, _countof(this->m_chaine)-1); + strncpy_s(m_chaine, _countof(m_chaine), nomChaine, _countof(m_chaine)-1); } /** * Définit le nom et heure du programme passé en paramètre * - * \param[in] heure la date/heure du déut du programme - * \param[in] programme le nom du programme - * \param[in] num position du programme + * \param[in] emis Structure d'écrivant le programme + * \param[in] num Position du programme (0 = actuel, 1 = suivant) **/ -void CLcd::SetProgramme(const SYSTEMTIME &heure, LPCTSTR programme, const int num){ - if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici - - TimeToStr(heure, this->programmes[num].heure, _countof(this->programmes[num].heure)); - strcpy_T(this->programmes[num].prog, _countof(this->programmes[num].prog), programme); +void CLcd::SetProgramme(const Emission & emis, int num) +{ + if (!m_initialise) + return; // Pas initialisé, donc, pas besoin de perdre du temps ici + if (!emis.isOk()) + return; + TimeToStr(emis.debut, programmes[num].heure, _countof(programmes[num].heure)); + strcpy_T(programmes[num].prog, emis.getName()); } - /** - * Définit le nom et heure du programme actuel - * - * \param[in] heure la date/heure du déut du programme - * \param[in] programme le nom du programme - **/ -void CLcd::SetProgrammeActuel(const SYSTEMTIME &heure, LPCTSTR programme){ - if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici - - SetProgramme(heure, programme, 0); -} - -/** - * Définit le nom et heure du programme suivant - * - * \param[in] heure la date/heure du déut du programme - * \param[in] programme le nom du programme - **/ -void CLcd::SetProgrammeSuivant(const SYSTEMTIME &heure, LPCTSTR programme){ - if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici - - SetProgramme(heure, programme, 1); -} - -/** * Fait passer le programme suivant en programme actuel **/ void CLcd::SetSuivant(){ Modifié: trunk/LCD.h =================================================================== --- trunk/LCD.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/LCD.h 2009-01-30 21:00:14 UTC (rev 170) @@ -57,7 +57,7 @@ /// heure de début de diffusion TCHAR heure[32]; /// nom du programme - char prog[256]; + char prog[256]; } programmes[2]; /// Volume @@ -77,20 +77,21 @@ **/ void UpdateTexte(); +public: + /** * Définit le nom et heure du programme passé en paramètre * - * \param[in] heure la date/heure du déut du programme - * \param[in] programme le nom du programme - * \param[in] num position du programme + * \param[in] emis Structure d'écrivant le programme + * \param[in] num Position du programme (0 = actuel, 1 = suivant) **/ - void SetProgramme(const SYSTEMTIME &heure, LPCTSTR programme, const int num); + void SetProgramme(const Emission & emis, int num); -public: enum { DEFAULT_POINTSIZE = 8, DEFAULT_DPI = 96, }; + CLcd(); ~CLcd(); @@ -110,29 +111,18 @@ void SetChaine(const char *nomChaine); /** - * Définit le nom et heure du programme actuel - * - * \param[in] heure la date/heure du déut du programme - * \param[in] programme le nom du programme - **/ - void SetProgrammeActuel(const SYSTEMTIME &heure, LPCTSTR programme); - /** - * Définit le nom et heure du programme suivant - * - * \param[in] heure la date/heure du déut du programme - * \param[in] programme le nom du programme - **/ - void SetProgrammeSuivant(const SYSTEMTIME &heure, LPCTSTR programme); - /** * Fait passer le programme suivant en programme actuel **/ void SetSuivant(); /// Définit le volume à afficher - void SetVolume(const long &volume) { this->m_volume = (volume+8000)/80; ActualiseLcd();} + void SetVolume(const long &volume) { + if (m_initialise) {m_volume = (volume+8000)/80;};} + /// On est en sourdine void Mute(const bool &muted) { this->m_mute = muted; ActualiseLcd(); } /// Indique si le LCD est initialisé - bool IsInitialise() { return this->m_initialise; } + bool IsInitialise() { + return m_initialise; } }; Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/channels.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -110,13 +110,11 @@ switch (son.type) { case ast_MPEG2: - hr = pMapSound->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); - myprintf(TEXT("%?erreur pid son, hr=0x%08x\n"), FAILED(hr), hr); + hr = branche_pid(pMapSound, pid IF_DEBUG_CB("Audio MPEG2")); break; case ast_AC3: - hr = pMapAc3->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); - myprintf(TEXT("%?erreur pid ac3, hr=0x%08x\n"), FAILED(hr), hr); + hr = branche_pid(pMapAc3, pid IF_DEBUG_CB("Audio AC3")); break; default: @@ -125,24 +123,12 @@ } } -static void debranche_son(une_piste son) +static HRESULT debranche_tous_pids(CComPtr & pMap IF_DEBUG_CB(LPCSTR nom_itf)); // forward + +static void debranche_son() { - ULONG pid = son.pid; - - if (pid!=0) - switch (son.type) { - - case ast_MPEG2: - pMapSound->UnmapPID(1, &pid); - break; - - case ast_AC3: - pMapAc3->UnmapPID(1, &pid); - break; - - default: - myprintf(TEXT("Type de piste audio non identifié\n")); - } + debranche_tous_pids(pMapSound IF_DEBUG_CB("Audio MPEG2")); + debranche_tous_pids(pMapAc3 IF_DEBUG_CB("Audio AC3")); } HBITMAP Chaine::ChargeIcone() @@ -181,26 +167,54 @@ return _stprintf_s(pstr, bufSize, TEXT("%4i : %") A2t, numeroChaine, nom); } -// Mappage de tous les PIDs de la chaîne (la fréquence est présumée déjà syntonisée) ; -// Si 'reset_son' est 'true', alors le canal son est, en même temps, remis à sa -// valeur par défaut, selon préférences globales de l'utilisateur : +/** + * Obtenir le nom de l'émission couramment en cours de diffusion + * \param[in] pszDefault Chaîne à retourner en l'absence de nom d'émission valide + * \retval Nom de l'émission, ou bien \p pszDefault si cette information n'est pas disponible + **/ +LPCTSTR Chaine::getCurrentProgramName(LPCTSTR pszDefault) const +{ + SYSTEMTIME localtime; + + GetLocalTime(&localtime); + + // Recherche d'une émission pour laquelle le temps courant est compris entre l'heure de + // début et l'heure de fin + for (UINT8 nInx=0; nInx=0 && DiffTime(localtime, emi.fin)<0) + return emi.nom; + } + return pszDefault; +} + +/** + * Mappage de tous les PIDs de la chaîne (la fréquence est présumée déjà syntonisée) ; + * Si \p reset_son est \p true, alors le canal son est, en même temps, remis à sa + * valeur par défaut, selon préférences globales de l'utilisateur + **/ HRESULT Chaine::branche(bool reset_son) const { - myprintf(TEXT("Branche SID=%i, TSID=%i, ONID=%i, freq=%i\n"), SID, TSID, ONID, khz); + ULONG pid = video_pid; - ULONG pid = video_pid; + myprintf(TEXT("Chaine::branche SID=%i, TSID=%i, ONID=%i, freq=%i\n"), SID, TSID, ONID, khz); + HRESULT hr = E_FAIL; // valeur par défaut if (pid) { switch (video_type) { case vst_MPEG2: - if (pMapMPEG2) - hr = pMapMPEG2->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); + hr = branche_pid(pMapMPEG2, pid IF_DEBUG_CB("Vidéo MPEG2")); break; +#ifdef TEST_H264 + case vst_H264: + hr = branche_pid(pMapH264, pid IF_DEBUG_CB("Vidéo H264")); + break; +#endif default: hr=E_FAIL; } - myprintf(TEXT("%?erreur pid video, hr=0x%08x\n"), FAILED(hr), hr); } if (reset_son) { @@ -219,15 +233,16 @@ branche_son(sons.tbl[ixSonCourant]); // pmt - pid = pmt_pid; - hr = pMapPmt->MapPID(1, &pid, MEDIA_MPEG2_PSI); - myprintf(TEXT("%?erreur pid pmt, hr=0x%08x\n"), FAILED(hr), hr); + hr = branche_pid(pMapPmt, pmt_pid IF_DEBUG_CB("PMT"), MEDIA_MPEG2_PSI); return hr; } /** - * Recherche de l'index correspondant à un numéro de chaîne 'numChaine'. - * Retourne -1 si pas trouvé. + * Recherche d'une chaîne en partant de son numéro + * \param[in] numChaine Numéro de la chaîne, tel que défini dans la configuration des + * chaînes et tel qu'affiché à l'utilisateur + * \retval Index de la chaîne dans la table #Canaux + * \retval -1 si le numéro n'a pas été trouvé **/ int trouve_chaine_par_no(WORD numChaine) { @@ -241,8 +256,10 @@ } /** - * Recherche de l'index correspondant à un service ID de chaîne 'sidChaine'. - * Retourne -1 si pas trouvé. + * Recherche d'une chaîne en partant de son SID ("Service ID") + * \param[in] sidChaine SID de la chaîne, tel que spécifié dans le flux TS + * \retval Index de la chaîne dans la table #Canaux + * \retval -1 si le numéro n'a pas été trouvé **/ int trouve_chaine_par_sid(WORD sidChaine) { @@ -257,6 +274,9 @@ /** * Trouver le SID correspodant à un index de chaîne. + * \param[in] ixChaine Index dans la table #Canaux + * \note Si on passe \p STREAM_PSEUDO_INDEX en paramètre, la fonction retourne \p STREAM_PSEUDO_SID. + * Ceci est utilisé en interne pour gérer les enregistrements de multiplex entier. **/ WORD indexToSID(int ixChaine) { @@ -266,9 +286,11 @@ } /** - * Trouve le premier numéro de chaîne inutilisé, pour pouvoir l'attribuer à une nouvelle chaîne. + * Trouver le premier numéro de chaîne inutilisé, en vue d'assignation à une nouvelle chaîne. + * \retval Numéro trouvé (intervalle 1 à 999) + * \retval 0 si plus aucun numéro disponible (hypothèse assez improbable) **/ -WORD nouveau_numero_chaine() +static WORD nouveau_numero_chaine() { for (WORD numChaine=1; numChaine<=999; numChaine++) { if (trouve_chaine_par_no(numChaine) < 0) @@ -278,7 +300,9 @@ } /** - * Retourne 'true' si l'index de chaîne passé en paramètre est valide. + * Vérification de la validité d'un index de chaîne + * \param[in] ixChaine Index dans la table #Canaux + * \retval \p true si l'index est valide. **/ bool ixChaine_ok(int ixChaine) { @@ -332,6 +356,10 @@ } } +/** + * Syntonisation d'une fréquence dans le tuner. + * \param[in] freq Fréquence à syntoniser, exprimée en kilohertz + **/ void change_frequence(ULONG freq) { if (pBDAControl && pBDAFreq) { @@ -352,7 +380,9 @@ } } -// S'assurer que le VMR a été initialisé : +/** + * S'assurer que le Video Mixing Renderer a été initialisé + **/ bool do_init_vmr() { HRESULT hr = init_vmr(); @@ -365,43 +395,77 @@ return true; } -// Débranchement de tous les flux élémentaires (identifiés par PID) qui sont couramment -// présentés sur la connexion pMap. -static void debranche_tous_pids(CComPtr & pMap IF_DEBUG_CB(LPCSTR nom_itf)) +/** + * Débranchement de tous les flux élémentaires (identifiés par PID) qui sont couramment + * présentés sur la connexion pMap (en sortie du démultiplexeur). + * \param[in] pMap Interface d'une broche de sortie du démultiplexeur + * \param[in] nom_itf Nom de la connexion pour debugging + **/ +static HRESULT debranche_tous_pids(CComPtr & pMap IF_DEBUG_CB(LPCSTR nom_itf)) { - PID_MAP maps[8]; - ULONG nbPids = 0; + HRESULT hr = S_OK; - if (pMap) { - CComPtr pEnumMap; +if (!pMap) + return E_FAIL; - pMap->EnumPIDMap(&pEnumMap); - pEnumMap->Next(_countof(maps), maps, &nbPids); + CComPtr pEnumMap; + + if (SUCCEEDED(hr = pMap->EnumPIDMap(&pEnumMap))) { + PID_MAP maps[8]; + ULONG nbPids = 0; + + if (pEnumMap->Next(_countof(maps), maps, &nbPids)==S_OK) { + for (ULONG i=0; iUnmapPID(1, &pid))) { + myprintf(TEXT("Échec UnmapPID(%u) (%") A2t TEXT("), hr=0x%08x\n"), pid, nom_itf, hr); + break; + } + } + } + } - myprintf(TEXT("debranche %u pid(s) sur pMap=%") A2t TEXT("\n"), nbPids, nom_itf); - for (ULONG i=0; iUnmapPID(1, &maps[i].ulPID); - myprintf(TEXT("%?unmap foiré, hr=0x%08x\n"), FAILED(hr), hr); - } + return hr; } -// Déconnexion globale des sorties vidéo et audio : +/** + * Branchement d'un flux élémentaire (identifiés par PID) sur la connexion pMap + * (en sortie du démultiplexeur). + * \param[in] pMap Interface d'une broche de sortie du démultiplexeur + * \param[in] pid N° de PID à y connecter + * \param[in] nom_itf Nom de la connexion pour debugging + * \param[in] eMsc Type de contenu (MEDIA_ELEMENTARY_STREAM par défaut) + **/ +HRESULT branche_pid(CComPtr & pMap, ULONG pid IF_DEBUG_CB(LPCSTR nom_itf), + MEDIA_SAMPLE_CONTENT eMsc) +{ + myprintf(TEXT("Branche pid=%u sur broche %") A2t TEXT("\n"), pid, nom_itf); + HRESULT hr = pMap->MapPID(1, &pid, eMsc); + myprintf(TEXT("%?Échec MapPID(%u) (%") A2t TEXT("), hr=0x%08x\n"), FAILED(hr), pid, nom_itf, hr); + return hr; +} + +/** + * Déconnexion globale des sorties vidéo et audio + **/ void debranche() { if (!suspendu) { - debranche_tous_pids(pMapMPEG2 IF_DEBUG_CB("pMapMPEG2")); - debranche_tous_pids(pMapSound IF_DEBUG_CB("pMapSound")); - debranche_tous_pids(pMapAc3 IF_DEBUG_CB("pMapAc3")); - debranche_tous_pids(pMapPmt IF_DEBUG_CB("pMapPmt")); - + debranche_tous_pids(pMapMPEG2 IF_DEBUG_CB("Vidéo MPEG2")); + debranche_son(); + debranche_tous_pids(pMapPmt IF_DEBUG_CB("PMT")); suspendu = true; } } -// Reconnexion globale des sorties vidéo et audio ; -// si 'reset_son' est 'true', alors le canal son est, en même temps, remis à sa -// valeur par défaut, selon les préférences globales de l'utilisateur : +/** + * Reconnexion globale des sorties vidéo et audio + * \param[in] reset_son \p true si le canal son doit en même temps être remis à sa + * valeur par défaut, selon les préférences globales de l'utilisateur + **/ bool rebranche(bool reset_son) { // Note : l'initialisation du VMR est en principe ici déjà faite (ce qui fait @@ -419,22 +483,32 @@ return false; } -void switch_audio(int new_son) +/** + * Changement de piste son + * \param[in] ixSon Index de la nouvelle piste audio dans la table \p sons + * des pistes de la chaîne + **/ +void switch_audio(int ixSon) { - if (new_son != ixSonCourant) { + if (ixSon != ixSonCourant) { const une_piste * son_courant = Canaux[ixChaineCourante].sons.tbl; - debranche_son(son_courant[ixSonCourant]); - branche_son(son_courant[new_son]); + debranche_son(); + branche_son(son_courant[ixSon]); - ixSonCourant=new_son; + ixSonCourant=ixSon; } } -// Changement de chaîne pour la chaîne dont l'index est donné en paramètre. -// Retourne 0 si pas d'erreur, 1 si le changement n'a pas pu avoir lieu -// (mettre -1 pour désactiver la sélection de chaîne) -HRESULT change_chaine(int ixChaine) +/** + * Changement de chaîne, sélection par index dans la table. + * \param[in] ixChaine Index dans la table #Canaux. + * (mettre -1 pour désactiver la sélection de chaîne) + * \param[in] bForceTune Si \p true, le tuner est resyntonisé même si la fréquence + * ne change pas + * \retval S_OK si pas d'erreur + **/ +HRESULT change_chaine(int ixChaine, bool bForceTune) { if ( !ixChaine_ok(ixChaine) && ixChaine != -1) { myprintf(TEXT("change_chaine(%d) invalide"), ixChaine); @@ -444,16 +518,18 @@ bool sauve_suspend = suspendu; bool reset_son = ixChaine!=ixChaineCourante; - if (ixChaine_ok(ixChaineCourante) && ixChaine_ok(ixChaine) && - Canaux[ixChaineCourante].khz == Canaux[ixChaine].khz && - Canaux[ixChaineCourante].video_type == Canaux[ixChaine].video_type) - { - freq_differente = false; + if (!bForceTune) { + if (ixChaine_ok(ixChaineCourante) && ixChaine_ok(ixChaine) && + Canaux[ixChaineCourante].khz == Canaux[ixChaine].khz && + Canaux[ixChaineCourante].video_type == Canaux[ixChaine].video_type) + { + freq_differente = false; + } + + if (freq_differente && recording()) + return S_FALSE; // On ne change pas de fréquence si enregistrement en cours } - if (freq_differente && recording()) - return S_FALSE; // On ne change pas de fréquence si enregistrement en cours - ixChaineCourante = -1; // doit être égal à -1 pendant les transitions (à cause du filtre PMT) if (!suspendu) { @@ -486,6 +562,10 @@ return S_OK; } +/** + * Changement de volume sonore + * \param[in] volume Nouveau volume sonore, valeur de 0 à 100 + **/ void set_volume(long volume) { CComQIPtr pBas(pGraph); Modifié: trunk/channels.h =================================================================== --- trunk/channels.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/channels.h 2009-01-30 21:00:14 UTC (rev 170) @@ -27,18 +27,33 @@ #pragma once +#include "base.h" #include "chanutils.h" +#include -struct Emission { - UINT64 cle; // Représentation simplifiée de l'heure de début pour comparaisons (0 si pas défini) - UINT16 eid; // "event id" - SYSTEMTIME debut; - SYSTEMTIME fin; - TCHAR nom[86]; - TCHAR desc[256]; +/// Structure décrivant une émission programmée +struct Emission +{ + UINT64 cle; //!< Représentation simplifiée de l'heure de début pour comparaisons (0 si pas défini) + UINT16 eid; //!< "event id" + SYSTEMTIME debut; //!< Heure de début + SYSTEMTIME fin; //!< Heure de fin + TCHAR nom[86]; //!< Nom de l'émission + TCHAR desc[256]; //!< Description + /// Constructeur Emission() { ZeroMemory(this, sizeof(*this));} + + /// Vérifie si l'émission est valide + /// \retval \p true si valide, \p false si non valide + bool isOk() const { + return cle != 0;} + + /// Obtenir le nom de l'émission + /// \retval Nom de l'émission si valide, chaîne vide si non valide + LPCTSTR getName() const { + return isOk() ? nom : TEXT("");} }; struct ChainePMT { @@ -120,61 +135,114 @@ /// Génération du nom affichable pour le menu int toMenuString(LPTSTR pstr, size_t bufSize) const; - /// Mappage de tous les PIDs de la chaîne (la fréquence est présumée déjà syntonisée) ; - /// Si \p reset_son est \p true, alors le canal son est, en même temps, remis à sa - /// valeur par défaut, selon préférences globales de l'utilisateur : + /** + * Obtenir le nom de l'émission couramment en cours de diffusion + * \param[in] pszDefault Chaîne à retourner en l'absence de nom d'émission valide + * \retval Nom de l'émission, ou bien \p pszDefault si cette information n'est pas disponible + **/ + LPCTSTR getCurrentProgramName(LPCTSTR pszDefault) const; + + /** + * Mappage de tous les PIDs de la chaîne (la fréquence est présumée déjà syntonisée) ; + * Si \p reset_son est \p true, alors le canal son est, en même temps, remis à sa + * valeur par défaut, selon préférences globales de l'utilisateur + **/ HRESULT branche(bool reset_son) const; }; /// Tableau des chaînes -extern std::vector Canaux; +extern std::vector Canaux; -extern int ixChaineCourante; // Index de la chaîne couramment utilisée -extern int ixSonCourant; // Index de la piste sonore couramment utilisée -extern bool suspendu; // 'true' si vidéo et audio suspendus (à l'initialisation, ou si minimisé + 'suspend_minimized') +extern int ixChaineCourante; //!< Index de la chaîne couramment utilisée +extern int ixSonCourant; //!< Index de la piste sonore couramment utilisée +extern bool suspendu; //!< \p true si vidéo et audio suspendus (à l'initialisation, ou si minimisé + \p suspend_minimized) +/** + * Syntonisation d'une fréquence dans le tuner. + * \param[in] freq Fréquence à syntoniser, exprimée en kilohertz + **/ void change_frequence(ULONG freq); +/** + * S'assurer que le Video Mixing Renderer a été initialisé + **/ bool do_init_vmr(); -// Changement de chaîne pour la chaîne dont l'index est donné en paramètre. -// Retourne 0 si pas d'erreur, 1 si le changement n'a pas pu avoir lieu -// (mettre -1 pour désactiver la sélection de chaîne) -HRESULT change_chaine(int ixChaine); +/** + * Changement de chaîne, sélection par index dans la table. + * \param[in] ixChaine Index dans la table #Canaux. + * (mettre -1 pour désactiver la sélection de chaîne) + * \param[in] bForceTune Si \p true, le tuner est resyntonisé même si la fréquence + * ne change pas + * \retval S_OK si pas d'erreur + **/ +HRESULT change_chaine(int ixChaine, bool bForceTune=false); -// Changement de piste son : -void switch_audio(int new_son); +/** + * Changement de piste son + * \param[in] ixSon Index de la nouvelle piste audio dans la table \p sons + * des pistes de la chaîne + **/ +void switch_audio(int ixSon); -// Changement de volume sonore : +/** + * Changement de volume sonore + * \param[in] volume Nouveau volume sonore, valeur de 0 à 100 + **/ void set_volume(long volume); -// Déconnexion globale des sorties vidéo et audio : +/** + * Branchement d'un flux élémentaire (identifiés par PID) sur la connexion pMap + * (en sortie du démultiplexeur). + * \param[in] pMap Interface d'une broche de sortie du démultiplexeur + * \param[in] pid N° de PID à y connecter + * \param[in] nom_itf Nom de la connexion pour debugging + * \param[in] eMsc Type de contenu (MEDIA_ELEMENTARY_STREAM par défaut) + **/ +HRESULT branche_pid(CComPtr & pMap, ULONG pid IF_DEBUG_CB(LPCSTR nom_itf), + MEDIA_SAMPLE_CONTENT eMsc=MEDIA_ELEMENTARY_STREAM); + +/** + * Déconnexion globale des sorties vidéo et audio + **/ void debranche(); -// Reconnexion globale des sorties vidéo et audio ; -// si 'reset_son' est 'true', alors le canal son est, en même temps, remis à sa -// valeur par défaut, selon les préférences globales de l'utilisateur : +/** + * Reconnexion globale des sorties vidéo et audio + * \param[in] reset_son \p true si le canal son doit en même temps être remis à sa + * valeur par défaut, selon les préférences globales de l'utilisateur + **/ bool rebranche(bool reset_son); /** - * Recherche de l'index correspondant à un numéro de chaîne 'numChaine'. - * Retourne -1 si pas trouvé. + * Recherche d'une chaîne en partant de son numéro + * \param[in] numChaine Numéro de la chaîne, tel que défini dans la configuration des + * chaînes et tel qu'affiché à l'utilisateur + * \retval Index de la chaîne dans la table #Canaux + * \retval -1 si le numéro n'a pas été trouvé **/ int trouve_chaine_par_no(WORD numChaine); /** - * Recherche de l'index correspondant à un service ID de chaîne 'sidChaine'. - * Retourne -1 si pas trouvé. + * Recherche d'une chaîne en partant de son SID ("Service ID") + * \param[in] sidChaine SID de la chaîne, tel que spécifié dans le flux TS + * \retval Index de la chaîne dans la table #Canaux + * \retval -1 si le numéro n'a pas été trouvé **/ int trouve_chaine_par_sid(WORD sidChaine); /** - * Retourne 'true' si l'index de chaîne passé en paramètre est valide. + * Vérification de la validité d'un index de chaîne + * \param[in] ixChaine Index dans la table #Canaux + * \retval \p true si l'index est valide. **/ inline bool ixChaine_ok(int ixChaine); /** * Trouver le SID correspodant à un index de chaîne. + * \param[in] ixChaine Index dans la table #Canaux + * \note Si on passe \p STREAM_PSEUDO_INDEX en paramètre, la fonction retourne \p STREAM_PSEUDO_SID. + * Ceci est utilisé en interne pour gérer les enregistrements de multiplex entier. **/ WORD indexToSID(int ixChaine); Modifié: trunk/epg.cpp =================================================================== --- trunk/epg.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/epg.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -54,7 +54,7 @@ const Emission & emis = canal.emis[noEmis]; - if (emis.cle == 0) + if (!emis.isOk()) return; COPY_STR_ON_STACK(TCHAR, canal_nom, canal.nom, taille); @@ -196,16 +196,7 @@ ListView_AjouteColonnes(hListItem, t_cols); remplit_table_epg(hListItem); - remplit_liste_methodes(GetDlgItem(hDlg, IDC_METHOD_EPG)); - remplit_liste_audio(GetDlgItem(hDlg, IDC_AUDIO_EPG)); - - // Sélectionne le dernier paramètre utilisé pour l'enregistrement - SendDlgItemMessage(hDlg, IDC_METHOD_EPG, CB_SETCURSEL, epg_typerecvideo, 0); - SendDlgItemMessage(hDlg, IDC_AUDIO_EPG, CB_SETCURSEL, epg_typerecaudio, 0); - - if (epg_typerecvideo != 1) - EnableWindow(GetDlgItem(hDlg, IDC_AUDIO_EPG), FALSE); - + init_methodes(hDlg); ShowCursor(TRUE); // Suspend la disparition temporisée du curseur return TRUE; } @@ -238,8 +229,8 @@ int dy = RHgt(sRect)-RHgt(sSavRect); // Déplacement ou redimensionnement des contrôles : - ChgCtlPos(hDlg, IDC_METHOD_EPG, 0, dy); - ChgCtlPos(hDlg, IDC_AUDIO_EPG, 0, dy); + ChgCtlPos(hDlg, IDC_METHOD, 0, dy); + ChgCtlPos(hDlg, IDC_AUDIO, 0, dy); ChgCtlPos(hDlg, IDC_RECORD, 0, dy); ChgCtlPos(hDlg, IDC_UPDATE, dx, dy); ChgCtlPos(hDlg, IDOK, dx, dy); @@ -249,16 +240,10 @@ case WM_COMMAND: switch(LOWORD(wParam)) { - case IDC_METHOD_EPG: - if (HIWORD(wParam) == CBN_SELCHANGE) { - int index = (int)SendDlgItemMessage(hDlg, IDC_METHOD_EPG, CB_GETCURSEL, 0, 0); - if (index == 0 || index ==2){ - EnableWindow(GetDlgItem( hDlg, IDC_AUDIO_EPG), FALSE); - } - if (index == 1) { - EnableWindow(GetDlgItem( hDlg, IDC_AUDIO_EPG), TRUE); - } - } + case IDC_METHOD: + case IDC_AUDIO: + if (HIWORD(wParam) == CBN_SELCHANGE) + update_methodes(hDlg); return TRUE; case IDOK: @@ -284,11 +269,10 @@ if (!chaineToProg(ixChaine, LOBYTE(HIWORD(item.lParam)), prog) || !prog.verifie(false)) return FALSE; - prog.methode = (MethodeEnregistrement)SendDlgItemMessage(hDlg, IDC_METHOD_EPG, CB_GETCURSEL, 0, 0); - prog.audio = (AudioMode)SendDlgItemMessage(hDlg, IDC_AUDIO_EPG, CB_GETCURSEL, 0, 0); - epg_typerecvideo = prog.methode; - epg_typerecaudio = prog.audio; + // Ces deux valeurs ont été extraites de la boîte de dialogue au moment de leur sélection : + prog.methode = epg_typerecvideo; + prog.audio = epg_typerecaudio; Programmes.push_back(prog); finalize_prog_change(); @@ -316,7 +300,11 @@ }; ListView_GetItem(hListItem, &item); - zappe_index(trouve_chaine_par_sid(LOWORD(item.lParam))); + + int ixChaine = trouve_chaine_par_sid(LOWORD(item.lParam)); + + if (ixChaine != ixChaineCourante) + zappe_index(ixChaine); } } else if (p->hdr.code == LVN_KEYDOWN) { // On a appuyé sur une touche dans la liste Modifié: trunk/grabber.h =================================================================== --- trunk/grabber.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/grabber.h 2009-01-30 21:00:14 UTC (rev 170) @@ -29,6 +29,7 @@ #include "capture.h" +/// Classe implémentant les méthodes "callback" à associer à un "Sample grabber" class CSampleGrabber : public CUnknown, public ISampleGrabberCB // The Filter Interface { CCapture * pCapture; @@ -57,7 +58,7 @@ } BYTE taille_paquet_buf; - union TS_packet paquet_buf; + TS_packet paquet_buf; void traite_paquet(const TS_packet & p); Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/graph.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -656,10 +656,7 @@ if (!pMapEpg) return E_NOINTERFACE; - ULONG pid = p_pid_EIT; - - pMapEpg->MapPID(1, &pid, MEDIA_MPEG2_PSI); - return hr; + return branche_pid(pMapEpg, p_pid_EIT IF_DEBUG_CB("EPG"), MEDIA_MPEG2_PSI); } static HRESULT render_pmtfilter(IMpeg2Demultiplexer * pMpeg2Demux) @@ -742,6 +739,8 @@ /** * Mise en route du graphe * \return Code d'erreur DirectShow + * \todo Voir s'il ne serait pas intéressant de démarrer et arrêter le graphe dans un + * "thread" distinct afin d'éviter que l'application "gèle" pendant cette opération. **/ HRESULT graph_Run() { @@ -810,12 +809,12 @@ LONG_PTR param1, param2; #if USE_CONSOLE TCHAR buffer[MAX_ERROR_TEXT_LEN]; + int nEvCount = 0; // Comptage des événements traités en même temps #endif while (SUCCEEDED(pEvents->GetEvent(&evCode, ¶m1, ¶m2, 0))) { #if USE_CONSOLE - myprintf(TEXT("Graph Event 0x%02x=EC_%") A2t TEXT(", %08x, %08x\n"), evCode, - evCode==EC_VMR_RENDERDEVICE_SET ? "VMR_RENDERDEVICE_SET" : // 0x53 + myprintf(TEXT("Graph Event (%u) 0x%02x=EC_%") A2t TEXT(", %08x, %08x\n"), ++nEvCount, evCode, EnumToString(evCode, "BASE\0" // 0x00 "COMPLETE\0" // 0x01 @@ -841,8 +840,46 @@ "WINDOW_DESTROYED\0" // 0x15 "DISPLAY_CHANGED\0" // 0x16 "STARVATION\0" // 0x17 - // oui, bon, y'en a au moins 80 définis comme ça, - // on rajoutera la suite plus tard si besoin est ... + "OLE_EVENT\0" // 0x18 + "NOTIFY_WINDOW\0" // 0x19 + "STREAM_CONTROL_STOPPED\0" // 0x1a + "STREAM_CONTROL_STARTED\0" // 0x1b + "END_OF_SEGMENT\0" // 0x1c + "SEGMENT_STARTED\0" // 0x1d + "LENGTH_CHANGED\0" // 0x1e + "DEVICE_LOST\0" // 0x1f + "SAMPLE_NEEDED\0" // 0x20 + "PROCESSING_LATENCY\0" // 0x21 + "SAMPLE_LATENCY\0" // 0x22 + "SCRUB_TIME\0" // 0x23 + "STEP_COMPLETE\0" // 0x24 + "EC_SKIP_FRAMES\0" // 0x25 + "??\0??\0??\0??\0??\0" // 0x26 à 0x2a + "??\0??\0??\0??\0??\0" // 0x2b à 0x2f + "TIMECODE_AVAILABLE\0" // 0x30 + "EXTDEVICE_MODE_CHANGE\0" // 0x31 + "STATE_CHANGE\0" // 0x32 + "??\0??\0??\0??\0??\0??\0??\0" // 0x33 à 0x39 + "??\0??\0??\0??\0??\0??\0" // 0x3a à 0x3f + "PLEASE_REOPEN\0" // 0x40 + "STATUS\0" // 0x41 + "MARKER_HIT\0" // 0x42 + "LOADSTATUS\0" // 0x43 + "FILE_CLOSED\0" // 0x44 + "ERRORABORTEX\0" // 0x45 + "EOS_SOON\0" // 0x46 + "CONTENTPROPERTY_CHANGED\0" // 0x47 + "BANDWIDTHCHANGE\0" // 0x48 + "VIDEOFRAMEREADY\0" // 0x49 + "??\0??\0??\0??\0??\0??\0" // 0x4a à 0x4f + "GRAPH_CHANGED\0" // 0x50 + "CLOCK_UNSET\0" // 0x51 + "??\0" // 0x52 + "VMR_RENDERDEVICE_SET\0" // 0x53 + "VMR_SURFACE_FLIPPED\0" // 0x54 + "VMR_RECONNECTION_FAILED\0" // 0x55 + "PREPROCESS_COMPLETE\0" // 0x56 + "CODECAPI_EVENT\0" // 0x57 ), param1, param2); #endif Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/ini.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -170,9 +170,10 @@ **/ TCHAR motif_noms_enreg[MAX_PATH]; -int epg_typerecvideo; //!< Type d'enregistrement précédement utilisé dans la +MethodeEnregistrement + epg_typerecvideo; //!< Type d'enregistrement précédement utilisé dans la //!< fenêtre EPG pour la vidéo -int epg_typerecaudio; //!< Type d'enregistrement précédement utilisé dans la +AudioMode epg_typerecaudio; //!< Type d'enregistrement précédement utilisé dans la //!< fenêtre EPG pour l'audio @@ -221,9 +222,10 @@ // Sections dans le fichier de config // ==================================================================================== static TCHAR ini_config[] = TEXT("Config"); ///< Nom de la section contenant la configuration -static TCHAR ini_filtre_MPEG2[] = TEXT("Filtre MPEG2\0(debug)"); -static TCHAR ini_filtre_audio[] = TEXT("Filtre audio\0(debug)"); -static TCHAR ini_filtre_ac3[] = TEXT("Filtre AC3\0(debug)"); + +static TCHAR ini_filtre_MPEG2[] = TEXT("Filtre MPEG2"); +static TCHAR ini_filtre_audio[] = TEXT("Filtre audio"); +static TCHAR ini_filtre_ac3[] = TEXT("Filtre AC3"); static TCHAR ini_nom_ville[] = TEXT("Ville"); static TCHAR ini_strict[] = TEXT("Recherche stricte"); static TCHAR ini_chaine_courante[] = TEXT("Identifiant chaîne courante"); @@ -1119,6 +1121,30 @@ } /** + * Sauve un nom de pilote passé en paramètre. + * Gère le cas de la présence d'un debugger. + * + * \param[in] lpKeyName nom de la clé devant être utilisée + * \param[in] lpString chaîne de caractères à enregistrer + * \retval "une valeur non nulle" en cas de succès + * \retval 0 en cas d'erreur + **/ +static BOOL save_driver_str(LPCTSTR lpKeyName, LPCTSTR lpString) +{ + TCHAR szActualName[64]; + + strcpy_T(szActualName, lpKeyName); +#ifdef _WIN64 + // Utilisation d'appellations distinctes en OS 64 bits : les deux versions peuvent + // y exister concurremment, et les pilotes ou codecs vus par chacune sont différents. + strcat_T(szActualName, TEXT(" (x64)")); +#endif + if (IsDebuggerPresent()) + strcat_T(szActualName, TEXT(" (debug)")); + return save_config_str(szActualName, lpString); +} + +/** * Écrit une valeur numérique * * \param[in] lpKeyName nom de la clé devant être utilisée @@ -1229,12 +1255,12 @@ void save_config(void) { - save_config_str(ini_tuner, nom_tuner); - save_config_str(ini_receiver, nom_receiver); + save_driver_str(ini_tuner, nom_tuner); + save_driver_str(ini_receiver, nom_receiver); save_config_int(ini_offset_tuner, offset_tuner); - save_config_str(ini_filtre_MPEG2, filtreMPEG2); - save_config_str(ini_filtre_audio, filtreAudio); - save_config_str(ini_filtre_ac3, filtreAc3); + save_driver_str(ini_filtre_MPEG2, filtreMPEG2); + save_driver_str(ini_filtre_audio, filtreAudio); + save_driver_str(ini_filtre_ac3, filtreAc3); save_config_str(ini_nom_ville, nomVille); save_config_str(ini_motif_noms_enreg, motif_noms_enreg); save_config_bool(ini_strict, exact_match); @@ -1262,7 +1288,10 @@ save_config_winpos(ini_position_console, GetConsoleWindow()); #endif // #if USE_CONSOLE==1 save_config_int(ini_volume, volumeCourant); - save_config_assoc(ini_epg_typerecvideo, aEpgRecVideo, epg_typerecvideo); + + if (epg_typerecvideo!=meth_multiplex) // On ne sauve pas le mode "enregistrement du multiplex" + save_config_assoc(ini_epg_typerecvideo, aEpgRecVideo, epg_typerecvideo); + save_config_assoc(ini_epg_typerecaudio, aEpgRecAudio, epg_typerecaudio); save_config_raccourcis(); } @@ -1306,6 +1335,42 @@ } /** + * Cherche un nom de pilote dans le fichier de configuration. + * Gère le cas de la présence d'un debugger. + * + * \param[in] lpKeyName nom de l'option rechercher + * \param[out] lpValue valeur recherchée + * \param[in] bufSize nombre de caractères dans la chaîne de retours + * \return Nombre de caractères copiés, sans tenir compte du caractère '\\0' + **/ +static DWORD load_driver_str(LPCTSTR lpKeyName, LPTSTR lpValue, DWORD bufSize) +{ + TCHAR szActualName[64]; + bool bDebug = IsDebuggerPresent()!=0; + + strcpy_T(szActualName, lpKeyName); +#ifdef _WIN64 + // Utilisation d'appellations distinctes en OS 64 bits : les deux versions peuvent + // y exister concurremment, et les pilotes ou codecs vus par chacune sont différents. + strcat_T(szActualName, TEXT(" (x64)")); + if (bDebug) + strcat_T(szActualName, TEXT(" (debug)")); + + DWORD nLen = load_config_str(szActualName, lpValue, bufSize); + + if (nLen) + return nLen; + + // En cas d'échec, il se peut que la configuration ait été faite avec une ancienne + // version 64 bits. Au cas où, on réessaie avec l'ancien nom : + strcpy_T(szActualName, lpKeyName); +#endif + if (bDebug) + strcat_T(szActualName, TEXT(" (debug)")); + return load_config_str(szActualName, lpValue, bufSize); +} + +/** * Cherche une valeur numérique dans le fichier de configuration * * \param[in] lpKeyName nom de l'option rechercher @@ -1480,16 +1545,14 @@ strcpy_T(confPathName, (LPCTSTR)chemin_config); // Recherche si on a un fichier de config dans AppData - load_config_str(ini_tuner, nom_tuner, _countof(nom_tuner)); - if (nom_tuner[0] == 0) { + if (load_driver_str(ini_tuner, nom_tuner, _countof(nom_tuner)) == 0) { // Pas de tuner trouvé. On recherche dans le dossier courant strcpy_T(confPathName, pouchindir_prog); strcat_T(confPathName, prefix_conf); strcat_T(confPathName, config_file); - load_config_str(ini_tuner, nom_tuner, _countof(nom_tuner)); // Vérifie si on a une réponse - if (nom_tuner[0] == 0) + if (load_driver_str(ini_tuner, nom_tuner, _countof(nom_tuner)) == 0) // Comme fichier config.ini n'existe pas non plus, restauration du chemin vers %AppData% strcpy_T(confPathName, (LPCTSTR)chemin_config); else @@ -1498,30 +1561,13 @@ strcpy_T(pouchindir_conf, pouchindir_prog); } - static bool bFirstCall = true; + load_driver_str(ini_receiver, nom_receiver, _countof(nom_receiver)); + load_driver_str(ini_filtre_MPEG2, filtreMPEG2, _countof(filtreMPEG2)); - if (bFirstCall) { - // Ceci est exécuté seulement une fois au premier appel de la fonction : - if (IsDebuggerPresent()) { - // Présence d'un debugger : on utilise des noms de fichiers de configuration - // distincts pour les codecs, afin de pouvoir, dans ces conditions, éviter - // les codecs propriétaires protégés qui bloquent l'application. + offset_tuner = load_config_int(ini_offset_tuner, 0); - // Pour se faire, on écrit juste un espace à la place du zéro terminateur - // du nom concerné, pour "ouvrir" l'accès au mot "(debug)" qui se trouve - // derrière. - ini_filtre_MPEG2[strlen_T(ini_filtre_MPEG2)] = TCHAR(' '); - ini_filtre_audio[strlen_T(ini_filtre_audio)] = TCHAR(' '); - ini_filtre_ac3[strlen_T(ini_filtre_ac3)] = TCHAR(' '); - } - bFirstCall = false; - } - - load_config_str(ini_receiver, nom_receiver, _countof(nom_receiver)); - load_config_str(ini_filtre_MPEG2, filtreMPEG2, _countof(filtreMPEG2)); - offset_tuner = load_config_int(ini_offset_tuner, 0); - load_config_str(ini_filtre_audio, filtreAudio, _countof(filtreAudio)); - load_config_str(ini_filtre_ac3, filtreAc3, _countof(filtreAc3)); + load_driver_str(ini_filtre_audio, filtreAudio, _countof(filtreAudio)); + load_driver_str(ini_filtre_ac3, filtreAc3, _countof(filtreAc3)); load_config_str(ini_nom_ville, nomVille, _countof(nomVille)); load_config_str(ini_motif_noms_enreg, motif_noms_enreg, _countof(motif_noms_enreg), motif_noms_enreg_default); @@ -1559,8 +1605,8 @@ zoom_ratio = load_config_int(ini_zoom_ratio, 100); volumeCourant = load_config_int(ini_volume, 100); - epg_typerecvideo = load_config_assoc(ini_epg_typerecvideo, aEpgRecVideo, 0); - epg_typerecaudio = load_config_assoc(ini_epg_typerecaudio, aEpgRecAudio, 0); + epg_typerecvideo = (MethodeEnregistrement)load_config_assoc(ini_epg_typerecvideo, aEpgRecVideo, meth_TS); + epg_typerecaudio = (AudioMode)load_config_assoc(ini_epg_typerecaudio, aEpgRecAudio, audio_1); load_config_raccourcis(); } Modifié: trunk/ini.h =================================================================== --- trunk/ini.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/ini.h 2009-01-30 21:00:14 UTC (rev 170) @@ -83,6 +83,20 @@ etf_minimized ///< minimisée (en icône ou pas) }; +/// Spécification de la méthode d'enregistrement +enum MethodeEnregistrement { + meth_TS, //!< 0: L'enregistrement s'effectuera en mode TS + meth_PS, //!< 1: L'enregistrement s'effectuera en mode PS + meth_multiplex //!< 2: Le multiplex entier sera enregistré +}; + +/// Indique quelle piste audio sera utilisée dans un enregistrement +enum AudioMode { + audio_1, //!< Utilisation de la première piste MPEG2 disponible + audio_2, //!< Utilisation de la seconde piste MPEG2 disponible + audio_AC3 //!< Utilisation de la première piste AC3 disponible +}; + // ==================================================================================== // Variables de configuration // ==================================================================================== @@ -135,9 +149,11 @@ extern TCHAR motif_noms_enreg[MAX_PATH]; //!< Motifs pour les noms des enregistrements -extern int epg_typerecvideo; //!< Type d'enregistrement précédement utilisé dans la +extern MethodeEnregistrement + epg_typerecvideo; //!< Type d'enregistrement précédement utilisé dans la //!< fenêtre EPG pour la vidéo -extern int epg_typerecaudio; //!< Type d'enregistrement précédement utilisé dans la +extern AudioMode + epg_typerecaudio; //!< Type d'enregistrement précédement utilisé dans la //!< fenêtre EPG pour l'audio /** @} */ // fin de configVars Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/main.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -797,15 +797,21 @@ strcpy_T(str, canal_courant.nom); SendMessage(hMainStatus, SB_SETTEXT, 0, (LPARAM)str); +#ifdef USE_LOGITECH_LCD + lcd.SetChaine(canal_courant.nom); +#endif for (int nEmis=0; nEmis<=1; nEmis++) { const Emission & emis = canal_courant.emis[nEmis]; str[0] = 0; - if (emis.cle) + if (emis.isOk()) TimeToStr(emis.debut, str, _countof(str)); SendMessage(hMainStatus, SB_SETTEXT, nEmis*2+1, (LPARAM)str); - SendMessage(hMainStatus, SB_SETTEXT, nEmis*2+2, (LPARAM)(emis.cle ? emis.nom : TEXT(""))); + SendMessage(hMainStatus, SB_SETTEXT, nEmis*2+2, (LPARAM)(emis.getName())); +#ifdef USE_LOGITECH_LCD + lcd.SetProgramme(emis, nEmis); +#endif } if (!use_osd) { @@ -815,15 +821,9 @@ } #ifdef USE_LOGITECH_LCD - // Le LCD est OK - if (lcd.IsInitialise()) { - lcd.SetChaine(canal_courant.nom); - lcd.SetProgrammeActuel(canal_courant.emis[0].debut, canal_courant.emis[0].nom); - lcd.SetProgrammeSuivant(canal_courant.emis[1].debut, canal_courant.emis[1].nom); - lcd.SetVolume(volumeCourant); - lcd.ActualiseLcd(); - } -#endif // #ifdef USE_LOGITECH_LCD + lcd.SetVolume(volumeCourant); + lcd.ActualiseLcd(); +#endif if (use_msn && canal_courant.emi_count > 0) { HWND msnui = FindWindow(TEXT("MsnMsgrUIManager"), NULL); @@ -834,8 +834,8 @@ WCHAR buffer[1024]; swprintf_s(buffer, _countof(buffer), - L"\\0Music\\01\\0{0} - {1}\\0%S\\0%S\\0\\0\\0", - canal_courant.nom, canal_courant.emis[0].nom); + L"\\0Music\\01\\0{0} - {1}\\0%S\\0%" T2w L"\\0\\0\\0", + canal_courant.nom, canal_courant.getCurrentProgramName(TEXT(""))); msndata.dwData = 0x547; msndata.lpData = &buffer; @@ -849,18 +849,33 @@ /** * Changement de chaîne, sélection par index dans la table. + * Met également à jour les menus et la barre d'état. * \param[in] ixChaine Index dans la table #Canaux. * (mettre -1 pour désactiver la sélection de chaîne) **/ +HRESULT change_chaine_update(int ixChaine) +{ + HRESULT hr = change_chaine(ixChaine); + + if (hr==S_OK) { + update_all_menus(hMainWnd); + update_status_bar(); + } + return hr; +} + +/** + * Changement de chaîne, sélection par index dans la table. + * Met également à jour les menus, la barre d'état et l'affichage OSD. + * \param[in] ixChaine Index dans la table #Canaux. + * (mettre -1 pour désactiver la sélection de chaîne) + **/ void zappe_index(int ixChaine) { if (pOSD) pOSD->Clear(); // Effacer tous les objets OSD courants - if (change_chaine(ixChaine)==S_OK) { - update_all_menus(hMainWnd); - - update_status_bar(); + if (change_chaine_update(ixChaine)==S_OK) { // Programmer un timer pour effectuer certaines mises à jour (recalcul de // positionnement et affichage du nom de la chaîne et du programme en cours) // une fois que tout sera bien stabilisé (donc après un certain délai). @@ -1281,6 +1296,7 @@ #ifdef USE_LOGITECH_LCD lcd.SetVolume(volumeCourant); + lcd.ActualiseLcd(); #endif // #ifdef USE_LOGITECH_LCD if (pOSD) pOSD->DisplayVolume(volumeCourant); @@ -1288,25 +1304,27 @@ static void chaine_avance(int pas) // pas = 1 ou -1 { - int nbChaines = (int)Canaux.size(); - bool enregistre = recording()!=0; - long freq_courante = Canaux[ixChaineCourante].khz; + if (ixChaine_ok(ixChaineCourante)) { + int nbChaines = (int)Canaux.size(); + bool enregistre = recording()!=0; + long freq_courante = Canaux[ixChaineCourante].khz; - for (int i = ixChaineCourante ;; ) { - i = (i+nbChaines+pas)%nbChaines; - if (i==ixChaineCourante) - break; + for (int i = ixChaineCourante ;; ) { + i = (i+nbChaines+pas)%nbChaines; + if (i==ixChaineCourante) + break; - const Chaine & canal = Canaux[i]; + const Chaine & canal = Canaux[i]; - if (canal.etat != ec_preferee) - continue; // On ne retient que les chaînes "préférées" - if (enregistre && canal.khz != freq_courante) { - // Si enregistrement, la chaîne doit avoir la même fréquence - continue; + if (canal.etat != ec_preferee) + continue; // On ne retient que les chaînes "préférées" + if (enregistre && canal.khz != freq_courante) { + // Si enregistrement, la chaîne doit avoir la même fréquence + continue; + } + zappe_index(i); + break; } - zappe_index(i); - break; } } @@ -1694,8 +1712,7 @@ case IDM_CHAN_TUNE: myprintf(TEXT("Resyntonisation forcée\n")); - if (ixChaine_ok(ixChaineCourante)) - change_frequence(Canaux[ixChaineCourante].khz); + change_chaine(ixChaineCourante, true); break; default: @@ -1819,7 +1836,7 @@ switch (uMsg) { case WM_CREATE: { - myprintf(TEXT("create\n")); + myprintf(TEXT("Création fenêtre principale\n")); hMainWnd = hWnd; break; } @@ -2117,7 +2134,7 @@ case WM_APP_PMT_UPDATED: myprintf(TEXT("Le pmt a changé\n")); sauve_chaines(); - zappe_index(ixChaineCourante); + change_chaine_update(ixChaineCourante); if (pOSD) pOSD->UpdateRectsAndFont(); break; @@ -2647,7 +2664,7 @@ if (cmdOptions && cmdOptions->bMinimize) { // On a lancé avec le paramètre demandant de masquer la fenêtre if(!suspend_minimized) { - myprintf(TEXT("rebranche\n")); + myprintf(TEXT("Branchement des sorties audio et vidéo (mode minimisé)\n")); if (!rebranche(true)) return -1; } @@ -2657,16 +2674,14 @@ long freq_courante = Canaux[ixChaineCourante].khz; int ixChaineSauve = ixChaineCourante; - /* Force le changement de fréquence, sans quoi on a un écran noir au démarrage avec - le tuner USB Toshiba PX1256E-1TVH */ - for (int i=0; i(pe)) {} - const T & operator ++ () {pbeg = pbeg->next(); return *pbeg;} - const T & operator ++ (int) {const T * res = pbeg; pbeg = pbeg->next(); return *res;} - bool operator ! () const {return pbeg < pend;} - operator const T & () const {return *pbeg;} - operator const T * () const {return pbeg;} - const T & operator () () const {return *pbeg;}; + const T & operator ++ () { + pbeg = pbeg->next(); return *pbeg;} + const T & operator ++ (int) { + const T * res = pbeg; pbeg = pbeg->next(); return *res;} + bool operator ! () const { + return pbeg < pend;} + operator const T & () const { + return *pbeg;} + operator const T * () const { + return pbeg;} + const T & operator () () const { + return *pbeg;}; UINT32 size() const {return UINT32(pend-pbeg);} }; @@ -102,14 +108,14 @@ UINT8 hi; UINT8 lo; - operator UINT16() const - {return hi<<8 | lo;} - UINT16 operator () () const - {return UINT16(*this);} - UBE16 & operator = (UINT16 val) - {hi = UINT8(val>>8); lo=UINT8(val); return *this;}; - PUINT8 next() const - {return PUINT8(this+1);} + operator UINT16() const { + return hi<<8 | lo;} + UINT16 operator () () const { + return UINT16(*this);} + UBE16 & operator = (UINT16 val) { + hi = UINT8(val>>8); lo=UINT8(val); return *this;}; + PUINT8 next() const { + return PUINT8(this+1);} }; /// Représentation d'une valeur sur 32 bits au format "big endian" @@ -118,27 +124,27 @@ UBE16 hi; UBE16 lo; - operator UINT32() const - {return hi()<<16 | lo();} - UINT32 operator () () const - {return UINT32(*this);} - UBE32 & operator = (UINT32 val) - {hi = UINT16(val>>16); lo=UINT16(val); return *this;}; - PUINT8 next() const - {return PUINT8(this+1);} + operator UINT32() const { + return hi()<<16 | lo();} + UINT32 operator () () const { + return UINT32(*this);} + UBE32 & operator = (UINT32 val) { + hi = UINT16(val>>16); lo=UINT16(val); return *this;}; + PUINT8 next() const { + return PUINT8(this+1);} }; /// Modèle pour représenter 9 à 15 bits au format "big endian" template struct UBE : public UBE16 { - UINT16 operator () () const - {return UBE16::operator ()() & ((1< & operator = (UINT16 val) - {hi = UINT8(val>>8) | flags(); lo=UINT8(val); return *this;} + UINT16 operator () () const { + return UBE16::operator ()() & ((1< & operator = (UINT16 val) { + hi = UINT8(val>>8) | flags(); lo=UINT8(val); return *this;} }; typedef UBE<12> LEN12; // Longueur de champ sur 12 bits @@ -150,10 +156,10 @@ struct UINT8uw { UINT8 b; - UINT8 operator()() const - {return b;} - PUINT8 next() const - {return PUINT8(this+1);} + UINT8 operator()() const { + return b;} + PUINT8 next() const { + return PUINT8(this+1);} }; /**************************************************************************************** @@ -222,16 +228,16 @@ return UINT64(b[0] & 0x38)<<27 | UINT64(lo); } - UINT16 getExt() const - {return (b[4]&0x03)<<7 | b[5]>>1;} - PS_D_SCR & operator = (UINT64 val27M) - {return set(val27M/300, UINT16(val27M%300));} - UINT64 get27M() const - {return get90k()*300 + getExt();} - operator UINT64() const - {return get90k()*300 + getExt();} - PUINT8 next() const - {return PUINT8(this+1);} + UINT16 getExt() const { + return (b[4]&0x03)<<7 | b[5]>>1;} + PS_D_SCR & operator = (UINT64 val27M) { + return set(val27M/300, UINT16(val27M%300));} + UINT64 get27M() const { + return get90k()*300 + getExt();} + operator UINT64() const { + return get90k()*300 + getExt();} + PUINT8 next() const { + return PUINT8(this+1);} }; /** \brief Description du Time Stamp utilisé pour PTS ou DTS @@ -277,14 +283,14 @@ return UINT64(b[0] & 0x0e) << 29 | UINT64(lo); } - PS_D_TimeStamp & operator = (UINT64 val27M) - {return set(val27M/300);} - UINT64 get27M() const - {return get90k()*300;} - operator UINT64() const - {return get90k()*300;} - PUINT8 next() const - {return PUINT8(this+1);} + PS_D_TimeStamp & operator = (UINT64 val27M) { + return set(val27M/300);} + UINT64 get27M() const { + return get90k()*300;} + operator UINT64() const { + return get90k()*300;} + PUINT8 next() const { + return PUINT8(this+1);} }; typedef PS_D_TimeStamp MPEG_DTS; @@ -335,16 +341,16 @@ return UINT64(lo) | UINT64(hi)<<32; } - UINT16 getExt() const - {return MAKEWORD(b[5], b[4]) & 0x1ff;} - TS_PCR & operator = (UINT64 val27M) - {return set(val27M/300, UINT16(val27M%300));} - UINT64 get27M() const - {return get90k()*300 + getExt();} - operator UINT64() const - {return get90k()*300 + getExt();} - PUINT8 next() const - {return PUINT8(this+1);} + UINT16 getExt() const { + return MAKEWORD(b[5], b[4]) & 0x1ff;} + TS_PCR & operator = (UINT64 val27M) { + return set(val27M/300, UINT16(val27M%300));} + UINT64 get27M() const { + return get90k()*300 + getExt();} + operator UINT64() const { + return get90k()*300 + getExt();} + PUINT8 next() const { + return PUINT8(this+1);} }; /* @@ -383,10 +389,10 @@ b[2] = UINT8(rate << 2) | 0x03; return *this; } - operator UINT32() const - {return MAKELONG(MAKEWORD(b[2], b[1]), b[0] & 0x3f) >> 2;} - PUINT8 next() const - {return PUINT8(this+1);} + operator UINT32() const { + return MAKELONG(MAKEWORD(b[2], b[1]), b[0] & 0x3f) >> 2;} + PUINT8 next() const { + return PUINT8(this+1);} }; /****************************************************************************************/ @@ -416,10 +422,10 @@ b[2] = UINT8(rate << 1) | 0x01; return *this; } - operator UINT32() const - {return MAKELONG(MAKEWORD(b[2], b[1]), b[0] & 0x7f) >> 1;} - PUINT8 next() const - {return PUINT8(this+1);} + operator UINT32() const { + return MAKELONG(MAKEWORD(b[2], b[1]), b[0] & 0x7f) >> 1;} + PUINT8 next() const { + return PUINT8(this+1);} }; /**************************************************************************************** @@ -454,12 +460,12 @@ struct C3CHAR { CHAR code[3]; - void get(LPSTR str) const // str doit réserver au moins 4 caractères - {str[0] = code[0]; str[1] = code[1]; str[2] = code[2]; str[3] = 0;} - void get(LPWSTR str) const // str doit réserver au moins 4 caractères - {str[0] = code[0]; str[1] = code[1]; str[2] = code[2]; str[3] = 0;} - operator FOURCC() const - {return MAKEFOURCC(code[0], code[1], code[2], 0);}; + void get(LPSTR str) const { // str doit réserver au moins 4 caractères + str[0] = code[0]; str[1] = code[1]; str[2] = code[2]; str[3] = 0;} + void get(LPWSTR str) const { // str doit réserver au moins 4 caractères + str[0] = code[0]; str[1] = code[1]; str[2] = code[2]; str[3] = 0;} + operator FOURCC() const { + return MAKEFOURCC(code[0], code[1], code[2], 0);}; }; typedef C3CHAR ISO639_LANG; //!< Code de langue @@ -502,9 +508,10 @@ mdt_Private_Data = 0x5f, // mdt_Data_Broadcast_ID = 0x66, - mdt_AC3_Audio = 0x6a, + mdt_AC3_Audio = 0x6a, // DVB mdt_Extended_AC3_Audio = 0x7a, // + mdt_AC3_Audio__2 = 0x81, // DCII ou ATSC mdt_Logical_Channel = 0x83 // /* codes 0x95 à 0xa1 à identifier - ... SCTE ou ATSC ??? */ @@ -572,23 +579,23 @@ UINT8 _tag; // enum MDescriptorTag UINT8 length; - MDescriptorTag tag() const - {return static_cast(_tag);} - PUINT8 data() const - {return PUINT8(this+1);} - MDescriptor * next() const - {return reinterpret_cast(data() + length);} - template const T & as() const // Dérivation vers un type de descripteur spécifique - {return *reinterpret_cast(this);} + MDescriptorTag tag() const { + return static_cast(_tag);} + PUINT8 data() const { + return PUINT8(this+1);} + MDescriptor * next() const { + return reinterpret_cast(data() + length);} + template const T & as() const { // Dérivation vers un type de descripteur spécifique + return *reinterpret_cast(this);} }; /// Modèle pour les descripteurs contenant des suites répétitives template struct MDescriptor_list : public MDescriptor { - const T & operator () () const - {return *reinterpret_cast(this+1);} - streamScanner subDescrRange() const - {return streamScanner(data(), data() + length);} + const T & operator () () const { + return *reinterpret_cast(this+1);} + streamScanner subDescrRange() const { + return streamScanner(data(), data() + length);} }; /// \brief Sous-descripteur générique pour les chaînes @@ -597,13 +604,13 @@ { UINT8 strlen; - template UINT get(T dst, UINT bufsize) const - {return get_raw_str(LPCSTR(this+1), strlen, dst, bufsize);} - template UINT get(T (&dst)[S]) const - {return get(dst, S);} + template UINT get(T dst, UINT bufsize) const { + return get_raw_str(LPCSTR(this+1), strlen, dst, bufsize);} + template UINT get(T (&dst)[S]) const { + return get(dst, S);} - const MSubDescr_str * next() const - {return reinterpret_cast(this+1+strlen);} + const MSubDescr_str * next() const { + return reinterpret_cast(this+1+strlen);} }; // Instantiation qui revient souvent : @@ -625,16 +632,16 @@ struct MSubDescr_05 : public UINT8uw { - const MSubDescr_05 * next() const - {return this+1;} + const MSubDescr_05 * next() const { + return this+1;} }; struct MDescriptor_05 : public MDescriptor // tag = mdt_Registration { UBE32 format_identifier; - streamScanner subDescrRange() const - {return streamScanner(this+1, PUINT8(this+1) + length);} + streamScanner subDescrRange() const { + return streamScanner(this+1, PUINT8(this+1) + length);} }; /* Conditional access descriptor tag 0x09 @@ -655,8 +662,8 @@ struct MSubDescr_09 : public UINT8uw { - const MSubDescr_09 * next() const - {return this+1;} + const MSubDescr_09 * next() const { + return this+1;} }; struct MDescriptor_09 : public MDescriptor // tag = mdt_Conditional_Access @@ -664,8 +671,8 @@ UBE16 ca_system_id; PID13 ca_pid; - streamScanner subDescrRange() const - {return streamScanner(this+1, PUINT8(this+1) + length);} + streamScanner subDescrRange() const { + return streamScanner(this+1, PUINT8(this+1) + length);} }; /* ISO 639 Language Descriptor (PMT) tag 0x0a @@ -687,8 +694,8 @@ ISO639_LANG language_code; UINT8 audio_type; - const MSubDescr_0a * next() const - {return this+1;} + const MSubDescr_0a * next() const { + return this+1;} }; typedef MDescriptor_list MDescriptor_0a; // tag = mdt_ISO_639_Language @@ -709,8 +716,8 @@ { UINT8 _mb[3]; - UINT32 maximum_bitrate() const - {return ((_mb[0] & 0x3f)<<16)|(_mb[1]<<8)|(_mb[2]);} + UINT32 maximum_bitrate() const { + return ((_mb[0] & 0x3f)<<16)|(_mb[1]<<8)|(_mb[2]);} }; /* Network Name (NIT) tag 0x40 @@ -728,10 +735,10 @@ struct MDescriptor_40 : public MDescriptor // tag = mdt_Network_Name { - template UINT get_network_name(T dst, UINT bufsize) const - {return get_raw_str(LPCSTR(this+1), length, dst, bufsize);} - template UINT get_network_name(T (&dst)[S]) const - {return get_network_name(dst, S);} + template UINT get_network_name(T dst, UINT bufsize) const { + return get_raw_str(LPCSTR(this+1), length, dst, bufsize);} + template UINT get_network_name(T (&dst)[S]) const { + return get_network_name(dst, S);} }; /* Service List Descriptor (NIT) tag 0x41 @@ -753,8 +760,8 @@ UBE16 service_id; UINT8 service_type; // - const MSubDescr_41 * next() const - {return this+1;} + const MSubDescr_41 * next() const { + return this+1;} }; typedef MDescriptor_list MDescriptor_41; // tag = mdt_Service_List @@ -782,10 +789,10 @@ { UINT8 service_type; // - const MSubDescr_str & service_provider_name() const - {return *reinterpret_cast(this+1);}; - const MSubDescr_str & service_name() const - {return *service_provider_name().next();}; + const MSubDescr_str & service_provider_name() const { + return *reinterpret_cast(this+1);}; + const MSubDescr_str & service_name() const { + return *service_provider_name().next();}; }; /* Linkage descriptor (NIT) tag 0x4a @@ -882,10 +889,10 @@ { ISO639_LANG language_code; // - const MSubDescr_str & event_name() const - {return *reinterpret_cast(this+1);}; - const MSubDescr_str & text() const - {return *event_name().next();}; + const MSubDescr_str & event_name() const { + return *reinterpret_cast(this+1);}; + const MSubDescr_str & text() const { + return *event_name().next();}; }; /* Extended event descriptor (EIT) tag 0x4e @@ -918,13 +925,13 @@ struct MSubDescr_4e { - const MSubDescr_str & item_description() const - {return *reinterpret_cast(this);}; - const MSubDescr_str & item() const - {return *item_description().next();}; + const MSubDescr_str & item_description() const { + return *reinterpret_cast(this);}; + const MSubDescr_str & item() const { + return *item_description().next();}; - const MSubDescr_4e * next() const - {return reinterpret_cast(item().next());} + const MSubDescr_4e * next() const { + return reinterpret_cast(item().next());} }; struct MDescriptor_4e : public MDescriptor // tag = mdt_Extended_Event @@ -933,14 +940,14 @@ ISO639_LANG language_code; UINT8 length_of_items; // - UINT8 descriptor_number() const - {return UINT8(descriptor_numbers >> 4);} - UINT8 last_descriptor_number() const - {return UINT8(descriptor_numbers & 0x0f);} - streamScanner subDescrRange() const - {return streamScanner(this+1, PUINT8(this+1) + length_of_items);} - const MSubDescr_str & text() const - {return *reinterpret_cast(PUINT8(this+1)+length_of_items);}; + UINT8 descriptor_number() const { + return UINT8(descriptor_numbers >> 4);} + UINT8 last_descriptor_number() const { + return UINT8(descriptor_numbers & 0x0f);} + streamScanner subDescrRange() const { + return streamScanner(this+1, PUINT8(this+1) + length_of_items);} + const MSubDescr_str & text() const { + return *reinterpret_cast(PUINT8(this+1)+length_of_items);}; }; /* Component descriptor (EIT) tag 0x50 @@ -968,12 +975,12 @@ UINT8 component_tag; ISO639_LANG language_code; - UINT8 stream_content() const - {return UINT8(_stream_content & 0x0f);} - template UINT get_text_char(T dst, UINT bufsize) const - {return get_raw_str(LPCSTR(this+1), UINT(PUINT8(next())-PUINT8(this+1)), dst, bufsize);} - template UINT get_text_char(T (&dst)[S]) const - {return get_text_char(dst, S);} + UINT8 stream_content() const { + return UINT8(_stream_content & 0x0f);} + template UINT get_text_char(T dst, UINT bufsize) const { + return get_raw_str(LPCSTR(this+1), UINT(PUINT8(next())-PUINT8(this+1)), dst, bufsize);} + template UINT get_text_char(T (&dst)[S]) const { + return get_text_char(dst, S);} }; /* Stream identifier descriptor (PMT) tag 0x52 @@ -1013,17 +1020,17 @@ UINT8 content_nibbles; UINT8 user_nibbles; - UINT8 content_nibble_level_1() const - {return UINT8(content_nibbles>>4);} - UINT8 content_nibble_level_2() const - {return UINT8(content_nibbles&0x0f);} - UINT8 user_nibble_1() const - {return UINT8(user_nibbles>>4);} - UINT8 user_nibble_2() const - {return UINT8(user_nibbles&0x0f);} + UINT8 content_nibble_level_1() const { + return UINT8(content_nibbles>>4);} + UINT8 content_nibble_level_2() const { + return UINT8(content_nibbles&0x0f);} + UINT8 user_nibble_1() const { + return UINT8(user_nibbles>>4);} + UINT8 user_nibble_2() const { + return UINT8(user_nibbles&0x0f);} - const MSubDescr_54 * next() const - {return this+1;} + const MSubDescr_54 * next() const { + return this+1;} }; typedef MDescriptor_list MDescriptor_54; // tag = mdt_Content @@ -1047,8 +1054,8 @@ ISO3166_CTRY country_code; UINT8 rating; - const MSubDescr_55 * next() const - {return this+1;} + const MSubDescr_55 * next() const { + return this+1;} }; typedef MDescriptor_list MDescriptor_55; // tag = mdt_Parental_Rating @@ -1075,13 +1082,13 @@ UINT8 teletext_type_and_mag; UINT8 teletext_page_number; - UINT8 teletext_type() const - {return UINT8(teletext_type_and_mag>>3);} - UINT8 teletext_magazine_number() const - {return UINT8(teletext_type_and_mag&0x07);} + UINT8 teletext_type() const { + return UINT8(teletext_type_and_mag>>3);} + UINT8 teletext_magazine_number() const { + return UINT8(teletext_type_and_mag&0x07);} - const MSubDescr_56 * next() const - {return this+1;} + const MSubDescr_56 * next() const { + return this+1;} }; typedef MDescriptor_list MDescriptor_56; // tag = mdt_Teletext @@ -1109,8 +1116,8 @@ UBE16 composition_page_id; UBE16 ancillary_page_id; - const MSubDescr_59 * next() const - {return this+1;} + const MSubDescr_59 * next() const { + return this+1;} }; typedef MDescriptor_list MDescriptor_59; // tag = mdt_Subtitling @@ -1144,22 +1151,22 @@ UINT8 data2; // code_rate-LP_stream, guard_interval, transmission_mode, other_frequency_flag UBE32 reserved2; - UINT8 bandwidth() const - {return UINT8(_bandwidth>>5);} - UINT8 constellation() const - {return UINT8(data1>>6);} - UINT8 hierarchy_information() const - {return UINT8((data1>>3)&0x07);} - UINT8 code_rate_HP_stream() const - {return UINT8(data1&0x07);} - UINT8 code_rate_LP_stream() const - {return UINT8(data2>>5);} - UINT8 guard_interval() const - {return UINT8((data2>>3)&0x03);} - UINT8 transmission_mode() const - {return UINT8((data2>>1)&0x03);} - UINT8 other_frequency_flag() const - {return UINT8(data2&0x01);} + UINT8 bandwidth() const { + return UINT8(_bandwidth>>5);} + UINT8 constellation() const { + return UINT8(data1>>6);} + UINT8 hierarchy_information() const { + return UINT8((data1>>3)&0x07);} + UINT8 code_rate_HP_stream() const { + return UINT8(data1&0x07);} + UINT8 code_rate_LP_stream() const { + return UINT8(data2>>5);} + UINT8 guard_interval() const { + return UINT8((data2>>3)&0x03);} + UINT8 transmission_mode() const { + return UINT8((data2>>1)&0x03);} + UINT8 other_frequency_flag() const { + return UINT8(data2&0x01);} }; /* Private Data Specifier tag 0x5f @@ -1217,8 +1224,8 @@ { UINT8 ac3_flags; - UINT8 flags() const - {return UINT8(ac3_flags & 0xf0);} + UINT8 flags() const { + return UINT8(ac3_flags & 0xf0);} }; struct MDescriptor_6a_unwrapper @@ -1300,8 +1307,8 @@ struct MDescriptor_7a : public MDescriptor_6a // tag = mdt_Extended_AC3_Audio { - UINT8 flags() const - {return ac3_flags;} + UINT8 flags() const { + return ac3_flags;} }; /* Data broadcast id descriptor (PMT) tag 0x66 @@ -1345,16 +1352,16 @@ struct MSubDescr_66 : public UINT8uw { - const MSubDescr_66 * next() const - {return this+1;} + const MSubDescr_66 * next() const { + return this+1;} }; struct MDescriptor_66 : public MDescriptor // tag = mdt_Data_Broadcast_ID { UBE16 data_broadcast_id; - streamScanner subDescrRange() const - {return streamScanner(this+1, next());} + streamScanner subDescrRange() const { + return streamScanner(this+1, next());} }; /* Logical Channel Descriptor (NIT) tag 0x83 @@ -1377,8 +1384,8 @@ UBE16 service_id; UBE<10> logical_channel_number; // - const MSubDescr_83 * next() const - {return this+1;} + const MSubDescr_83 * next() const { + return this+1;} }; typedef MDescriptor_list MDescriptor_83; // tag = mdt_Logical_Channel @@ -1629,12 +1636,12 @@ UINT8 start_code[3]; UINT8 stream_id; - UINT32 get_start_code() const - {return MAKELONG(MAKEWORD(start_code[2], start_code[1]), start_code[0]);} - bool isPS() const - {return get_start_code()==0x000001;} - template const T & as() const // Dérivation vers un type de descripteur spécifique - {return *reinterpret_cast(this);} + UINT32 get_start_code() const { + return MAKELONG(MAKEWORD(start_code[2], start_code[1]), start_code[0]);} + bool isPS() const { + return get_start_code()==0x000001;} + template const T & as() const { // Dérivation vers un type de descripteur spécifique + return *reinterpret_cast(this);} // Constructeurs : PS_hdr() {} // neutre @@ -1647,14 +1654,14 @@ { UBE16 hdr_length; - PUINT8 base_of_data_size() const - {return PUINT8(this+1);} - void set_data_size(PUINT8 adr) - {hdr_length = UINT16(adr-base_of_data_size());} - UINT32 packet_size() const - {return sizeof(*this) + hdr_length();} - PUINT8 next() const - {return PUINT8(this) + packet_size();} + PUINT8 base_of_data_size() const { + return PUINT8(this+1);} + void set_data_size(PUINT8 adr) { + hdr_length = UINT16(adr-base_of_data_size());} + UINT32 packet_size() const { + return sizeof(*this) + hdr_length();} + PUINT8 next() const { + return PUINT8(this) + packet_size();} // Constructeur : PS_hdr_wl() {} // neutre @@ -1700,14 +1707,14 @@ PS_PH_mux_rate mux_rate; UINT8 length; // 3 bits de poids faible seulement - UINT32 stuffing_length() const - {return length & 0x07;} - UINT32 packet_size() const - {return sizeof(*this)+stuffing_length();} - PUINT8 end_of_header() const - {return PUINT8(this+1);} - PUINT8 end_of_packet() const - {return end_of_header()+stuffing_length();} + UINT32 stuffing_length() const { + return length & 0x07;} + UINT32 packet_size() const { + return sizeof(*this)+stuffing_length();} + PUINT8 end_of_header() const { + return PUINT8(this+1);} + PUINT8 end_of_packet() const { + return end_of_header()+stuffing_length();} // Constructeur PS_PackHeader() : @@ -1723,14 +1730,14 @@ { UBE<13> buffer_size; - UINT16 buffer_scale() const - {return buffer_size.flags() & PES_SB_BUFFERSCALE_FLAG ? 0x400 : 0x80;} - void set_size(bool scale, UINT16 size) - {buffer_size = size; buffer_size.set_flags(PES_SB_BUFFERSCALE_FLAG, scale ? PES_SB_BUFFERSCALE_FLAG : 0);} - UINT32 actual_buffer_size() const - {return buffer_size()*buffer_scale();} - PUINT8 next() const - {return PUINT8(this+1);} + UINT16 buffer_scale() const { + return buffer_size.flags() & PES_SB_BUFFERSCALE_FLAG ? 0x400 : 0x80;} + void set_size(bool scale, UINT16 size) { + buffer_size = size; buffer_size.set_flags(PES_SB_BUFFERSCALE_FLAG, scale ? PES_SB_BUFFERSCALE_FLAG : 0);} + UINT32 actual_buffer_size() const { + return buffer_size()*buffer_scale();} + PUINT8 next() const { + return PUINT8(this+1);} }; /* @@ -1768,10 +1775,10 @@ UINT8 stream_id; PS_D_StdBuff bound_buf; - bool isEot() const - {return (stream_id & 0x80)==0;} - const PS_SH_entry * next() const - {return this+1;} + bool isEot() const { + return (stream_id & 0x80)==0;} + const PS_SH_entry * next() const { + return this+1;} }; // ** Flags dans les champs de PS_SystemHeader : @@ -1791,29 +1798,29 @@ UINT8 video_bound_and_flags; // nombre maximal de flux vidéo (+ 3 flags) UINT8 packet_rate_restriction_flag; // + 7 bits réservés - UINT8 audio_bound() const - {return audio_bound_and_flags >> 2;}; - UINT8 video_bound() const - {return video_bound_and_flags & 0x1f;}; - bool fixed() const - {return (audio_bound_and_flags & SH_FIXED_FLAG)!=0;} - bool CSPS() const - {return (audio_bound_and_flags & SH_CSPS_FLAG)!=0;} - bool system_audio_lock() const - {return (video_bound_and_flags & SH_SYSTEM_AUDIO_LOCK_FLAG)!=0;} - bool system_video_lock() const - {return (video_bound_and_flags & SH_SYSTEM_VIDEO_LOCK_FLAG)!=0;} - bool packet_rate_restriction() const - {return (packet_rate_restriction_flag & SH_PACKET_RATE_RESTRICTION_FLAG)!=0;} + UINT8 audio_bound() const { + return audio_bound_and_flags >> 2;}; + UINT8 video_bound() const { + return video_bound_and_flags & 0x1f;}; + bool fixed() const { + return (audio_bound_and_flags & SH_FIXED_FLAG)!=0;} + bool CSPS() const { + return (audio_bound_and_flags & SH_CSPS_FLAG)!=0;} + bool system_audio_lock() const { + return (video_bound_and_flags & SH_SYSTEM_AUDIO_LOCK_FLAG)!=0;} + bool system_video_lock() const { + return (video_bound_and_flags & SH_SYSTEM_VIDEO_LOCK_FLAG)!=0;} + bool packet_rate_restriction() const { + return (packet_rate_restriction_flag & SH_PACKET_RATE_RESTRICTION_FLAG)!=0;} // // Note : si, dans un élément, la fonction PS_SH_entry::isEot() retourne 'false', il se pourrait // qu'on doive comprendre que les éléments suivants ne sont pas valides, même si 'count' n'est pas épuisé. - int count() const - {return int(INT_PTR(next()-INT_PTR(this+1))/sizeof(PS_SH_entry));} - PS_SH_entry & operator [] (int index) - {return reinterpret_cast(this+1)[index];} - streamScanner entryRange() const - {return streamScanner(this+1, PUINT8(this+1) + hdr_length());} + int count() const { + return int(INT_PTR(next()-INT_PTR(this+1))/sizeof(PS_SH_entry));} + PS_SH_entry & operator [] (int index) { + return reinterpret_cast(this+1)[index];} + streamScanner entryRange() const { + return streamScanner(this+1, PUINT8(this+1) + hdr_length());} // Constructeur PS_SystemHeader() : @@ -1861,10 +1868,10 @@ UINT8 id; UBE16 dloop_length; - descrScanner descrRange() const - {return descrScanner(this+1, PUINT8(this+1) + dloop_length());} - PS_PSM_entry * next() const - {return reinterpret_cast(PUINT8(this+1) + dloop_length());} + descrScanner descrRange() const { + return descrScanner(this+1, PUINT8(this+1) + dloop_length());} + PS_PSM_entry * next() const { + return reinterpret_cast(PUINT8(this+1) + dloop_length());} }; // Seconde partie de PS_ProgramStreamMap, contenant la longueur de la table @@ -1873,8 +1880,8 @@ { UBE16 eloop_length; - streamScanner entryRange() const - {return streamScanner(this+1, PUINT8(this+1) + eloop_length());} + streamScanner entryRange() const { + return streamScanner(this+1, PUINT8(this+1) + eloop_length());} }; struct PS_ProgramStreamMap : public PS_hdr_wl @@ -1884,13 +1891,13 @@ UBE16 dloop_length; // Accès à la table de descripteurs incluse : - descrScanner descrRange() const - {return descrScanner(this+1, PUINT8(this+1) + dloop_length());} + descrScanner descrRange() const { + return descrScanner(this+1, PUINT8(this+1) + dloop_length());} // Accès aux champs suivant : - PS_PSM_entries_hdr & entries_hdr() const - {return *reinterpret_cast(PUINT8(this+1) + dloop_length());} - CRC_32 & crc32() const - {return *reinterpret_cast(next() - sizeof(CRC_32));} + PS_PSM_entries_hdr & entries_hdr() const { + return *reinterpret_cast(PUINT8(this+1) + dloop_length());} + CRC_32 & crc32() const { + return *reinterpret_cast(next() - sizeof(CRC_32));} // Constructeur : PS_ProgramStreamMap() : @@ -2062,8 +2069,8 @@ { UINT8 data[16]; - PUINT8 next() const - {return PUINT8(this+1);} + PUINT8 next() const { + return PUINT8(this+1);} }; struct PS_D_PackHdr @@ -2071,8 +2078,8 @@ UINT8 length; PS_PackHeader pack_header; - PUINT8 next() const - {return pack_header.end_of_packet();} + PUINT8 next() const { + return pack_header.end_of_packet();} }; struct PS_D_SeqCount @@ -2080,34 +2087,34 @@ UINT8 program_packet_sequence_counter; UINT8 original_stuff_length_and_id; // + MPEG1_MPEG2_identifier - UINT8 sequence_counter() const - {return program_packet_sequence_counter & 0x7f;} - UINT8 mpeg1_mpeg2_identifier() const - {return (original_stuff_length_and_id & 0x40) >> 6;} - UINT8 original_stuff_length() const - {return original_stuff_length_and_id & 0x3f;} - PUINT8 next() const - {return PUINT8(this+1);} + UINT8 sequence_counter() const { + return program_packet_sequence_counter & 0x7f;} + UINT8 mpeg1_mpeg2_identifier() const { + return (original_stuff_length_and_id & 0x40) >> 6;} + UINT8 original_stuff_length() const { + return original_stuff_length_and_id & 0x3f;} + PUINT8 next() const { + return PUINT8(this+1);} }; struct PS_D_extension1 { UINT8 flags; - PUINT8 begin() const - {return PUINT8(this+1);} - PUINT8 next() const - {return PUINT8(this+1);} + PUINT8 begin() const { + return PUINT8(this+1);} + PUINT8 next() const { + return PUINT8(this+1);} }; struct PS_D_extension2 { UINT8 length; - PUINT8 data() const - {return PUINT8(this+1);} - PUINT8 next() const - {return data() + length;} + PUINT8 data() const { + return PUINT8(this+1);} + PUINT8 next() const { + return data() + length;} }; // Définition des bits de "PS_hdr_wd::info" : @@ -2140,25 +2147,25 @@ UINT8 flags; UINT8 data_length; - UINT32 header_size() const - {return sizeof(*this)+data_length;} - PUINT8 base_of_data() const - {return PUINT8(this)+header_size();} - PUINT8 end_of_header() const - {return PUINT8(this)+header_size();} - PUINT8 beg_of_fields() const - {return PUINT8(this+1);} + UINT32 header_size() const { + return sizeof(*this)+data_length;} + PUINT8 base_of_data() const { + return PUINT8(this)+header_size();} + PUINT8 end_of_header() const { + return PUINT8(this)+header_size();} + PUINT8 beg_of_fields() const { + return PUINT8(this+1);} - UINT8 scrambling_control() const - {return UINT8((info >> 4) & 0x03);} - bool priority_flag() const - {return (info & PES_PRIORITY_FLAG) != 0;} - bool data_alignment() const - {return (info & DATA_ALIGNMENT_INDICATOR) != 0;} - bool copyrighted() const - {return (info & COPYRIGHT_FLAG) != 0;} - bool original() const - {return (info & ORIGINAL_FLAG) != 0;} + UINT8 scrambling_control() const { + return UINT8((info >> 4) & 0x03);} + bool priority_flag() const { + return (info & PES_PRIORITY_FLAG) != 0;} + bool data_alignment() const { + return (info & DATA_ALIGNMENT_INDICATOR) != 0;} + bool copyrighted() const { + return (info & COPYRIGHT_FLAG) != 0;} + bool original() const { + return (info & ORIGINAL_FLAG) != 0;} // Constructeurs : PS_hdr_wd() {} // neutre @@ -2225,6 +2232,25 @@ }; /**************************************************************************************** + * RTP * + ****************************************************************************************/ + +// Encapsulation RTP des flux TS rencontrée sur certains flux de diffusion : +// \test expérimental + +struct RTP_hdr +{ + UINT8 flags; + UINT8 payload_type; + UBE16 sequence_number; + UBE32 timestamp; + UBE32 synchronization_source; + + bool isRTP() const { + return (flags & 0xc0) == 0x80;} +}; + +/**************************************************************************************** * TRANSPORT STREAM * ****************************************************************************************/ @@ -2297,20 +2323,20 @@ PID13 pid; UINT8 control_and_ccounter; - bool transport_error_indicator() const - {return (pid.flags() & 0x80)!=0;} - bool payload_unit_start_indicator() const - {return (pid.flags() & 0x40)!=0;} - bool transport_priority() const - {return (pid.flags() & 0x20)!=0;} - ScramblingCtlValues transport_scrambling_control() const - {return ScramblingCtlValues((control_and_ccounter & 0xc0)>>6);} - AdaptationFieldCtlValues adaptation_field_control() const - {return AdaptationFieldCtlValues((control_and_ccounter & 0x30)>>4);} - UINT8 continuity_counter() const - {return control_and_ccounter & 0x0f;} - PUINT8 beg_of_fields() const - {return PUINT8(this+1);} + bool transport_error_indicator() const { + return (pid.flags() & 0x80)!=0;} + bool payload_unit_start_indicator() const { + return (pid.flags() & 0x40)!=0;} + bool transport_priority() const { + return (pid.flags() & 0x20)!=0;} + ScramblingCtlValues transport_scrambling_control() const { + return ScramblingCtlValues((control_and_ccounter & 0xc0)>>6);} + AdaptationFieldCtlValues adaptation_field_control() const { + return AdaptationFieldCtlValues((control_and_ccounter & 0x30)>>4);} + UINT8 continuity_counter() const { + return control_and_ccounter & 0x0f;} + PUINT8 beg_of_fields() const { + return PUINT8(this+1);} }; /* Adaptation Field @@ -2401,16 +2427,16 @@ UINT8 adaptation_field_length; UINT8 flags; - PUINT8 beg_of_fields() const - {return adaptation_field_length>0 ? PUINT8(this+1) : PUINT8(&flags);} - UINT8 get_flags() const - {return adaptation_field_length==0 ? 0 : flags;} - bool has_pcr() const - {return (get_flags() & AF_PCR_FLAG)!=0;} - const TS_PCR & get_pcr() const - {return *reinterpret_cast(beg_of_fields());} - PUINT8 next() const - {return PUINT8(&flags)+adaptation_field_length;} + PUINT8 beg_of_fields() const { + return adaptation_field_length>0 ? PUINT8(this+1) : PUINT8(&flags);} + UINT8 get_flags() const { + return adaptation_field_length==0 ? 0 : flags;} + bool has_pcr() const { + return (get_flags() & AF_PCR_FLAG)!=0;} + const TS_PCR & get_pcr() const { + return *reinterpret_cast(beg_of_fields());} + PUINT8 next() const { + return PUINT8(&flags)+adaptation_field_length;} }; struct TS_unwrapper @@ -2465,8 +2491,8 @@ { UINT8 length; - PUINT8 next() const - {return PUINT8(this+1) + length;} + PUINT8 next() const { + return PUINT8(this+1) + length;} }; struct TS_AF_extension @@ -2474,24 +2500,24 @@ UINT8 length; UINT8 flags; - PUINT8 next() const - {return PUINT8(this+1);} + PUINT8 next() const { + return PUINT8(this+1);} }; struct TS_AF_pw_rate { UINT8 piecewise_rate[3]; - PUINT8 next() const - {return PUINT8(this+1);} + PUINT8 next() const { + return PUINT8(this+1);} }; struct TS_AF_SlSplice { UINT8 seamless_splice[5]; - PUINT8 next() const - {return PUINT8(this+1);} + PUINT8 next() const { + return PUINT8(this+1);} }; struct TS_AF_unwrapper_full : public TS_AF_unwrapper_base @@ -2509,13 +2535,15 @@ #define TS_SYNC 0x47 // valeur de l'octet de synchronisation -union TS_packet +struct TS_packet { - TS_hdr hdr; - UINT8 bytes[TS_SIZE]; + union { + TS_hdr hdr; + UINT8 bytes[TS_SIZE]; + }; - bool isTS(bool single=false) const - {return hdr.sync_byte==TS_SYNC && (single || this[1].hdr.sync_byte==TS_SYNC);} + bool isTS(bool single=false) const { + return hdr.sync_byte==TS_SYNC && (single || this[1].hdr.sync_byte==TS_SYNC);} }; /**************************************************************************************** @@ -2666,29 +2694,29 @@ // Le même paramètre doit aussi être donné à toutes les fonctions qui font indirectement usage // de l'une de ces trois fonctions. // - SI_TableID table_id() const - {return static_cast(_table_id);} - bool section_syntax_indicator(bool microsoft=false) const - {return section_length.syntax_indicator(microsoft);} - UINT8 version_number() const - {return (versnum_and_next_indic & 0x3e)>>1;} - bool current_next_indicator() const - {return (versnum_and_next_indic & 0x01)!=0;} + SI_TableID table_id() const { + return static_cast(_table_id);} + bool section_syntax_indicator(bool microsoft=false) const { + return section_length.syntax_indicator(microsoft);} + UINT8 version_number() const { + return (versnum_and_next_indic & 0x3e)>>1;} + bool current_next_indicator() const { + return (versnum_and_next_indic & 0x01)!=0;} - PUINT8 begin() const - {return PUINT8(this+1);} - PUINT8 next(bool microsoft=false) const - {return PUINT8(§ion_id) + section_length(microsoft);} - size_t size(bool microsoft=false) const - {return next(microsoft)-PUINT8(this);} - PUINT8 end(bool microsoft=false) const - {return next(microsoft) - sizeof(CRC_32);} - const CRC_32 & crc32(bool microsoft=false) const - {return *reinterpret_cast(end(microsoft));} - template const T & as() const - {return *reinterpret_cast(this);} - bool check_crc32(bool microsoft=false) const - {return ::crc32(PUINT8(this), int(size(microsoft)))==0;} + PUINT8 begin() const { + return PUINT8(this+1);} + PUINT8 next(bool microsoft=false) const { + return PUINT8(§ion_id) + section_length(microsoft);} + size_t size(bool microsoft=false) const { + return next(microsoft)-PUINT8(this);} + PUINT8 end(bool microsoft=false) const { + return next(microsoft) - sizeof(CRC_32);} + const CRC_32 & crc32(bool microsoft=false) const { + return *reinterpret_cast(end(microsoft));} + template const T & as() const { + return *reinterpret_cast(this);} + bool check_crc32(bool microsoft=false) const { + return ::crc32(PUINT8(this), int(size(microsoft)))==0;} }; @@ -2772,20 +2800,20 @@ UBE16 program_number; // devrait peut-être être renommé en 'service_id' ?? PID13 pid; // - const SI_PAT_entry * next() const - {return this+1;} + const SI_PAT_entry * next() const { + return this+1;} }; struct SI_PAT : public SI_hdr { - UINT16 tsid(bool microsoft=false) const - {return section_id(microsoft);} - int count(bool microsoft=false) const - {return int((PUINT8(&crc32(microsoft))-begin())/sizeof(SI_PAT_entry));} - const SI_PAT_entry & operator [] (int index) const - {return reinterpret_cast(begin())[index];} - streamScanner entryRange(bool microsoft=false) const - {return streamScanner(begin(), end(microsoft));} + UINT16 tsid(bool microsoft=false) const { + return section_id(microsoft);} + int count(bool microsoft=false) const { + return int((PUINT8(&crc32(microsoft))-begin())/sizeof(SI_PAT_entry));} + const SI_PAT_entry & operator [] (int index) const { + return reinterpret_cast(begin())[index];} + streamScanner entryRange(bool microsoft=false) const { + return streamScanner(begin(), end(microsoft));} }; // ############################################################################ @@ -2816,8 +2844,8 @@ /// Représentation table PSI : CAT = Conditional Access Table struct SI_CAT : public SI_hdr { - descrScanner descrRange(bool microsoft=false) const - {return descrScanner(this+1, end(microsoft));} + descrScanner descrRange(bool microsoft=false) const { + return descrScanner(this+1, end(microsoft));} }; // ############################################################################ @@ -2890,12 +2918,12 @@ PID13 pid; LEN12 dloop_length; // - StreamType type() const - {return static_cast(_type);} - descrScanner descrRange() const - {return descrScanner(this+1, PUINT8(this+1) + dloop_length());} - const SI_PMT_entry * next() const - {return reinterpret_cast(PUINT8(this+1) + dloop_length());} + StreamType type() const { + return static_cast(_type);} + descrScanner descrRange() const { + return descrScanner(this+1, PUINT8(this+1) + dloop_length());} + const SI_PMT_entry * next() const { + return reinterpret_cast(PUINT8(this+1) + dloop_length());} }; // PMT = Program Map Table @@ -2904,12 +2932,12 @@ PID13 pid; LEN12 dloop_length; // - UINT16 program_number(bool microsoft=false) const - {return section_id(microsoft);} - descrScanner descrRange() const - {return descrScanner(this+1, PUINT8(this+1) + dloop_length());} - streamScanner entryRange(bool microsoft=false) const - {return streamScanner(PUINT8(this+1) + dloop_length(), end(microsoft));} + UINT16 program_number(bool microsoft=false) const { + return section_id(microsoft);} + descrScanner descrRange() const { + return descrScanner(this+1, PUINT8(this+1) + dloop_length());} + streamScanner entryRange(bool microsoft=false) const { + return streamScanner(PUINT8(this+1) + dloop_length(), end(microsoft));} }; // ############################################################################ @@ -2955,10 +2983,10 @@ LEN12 dloop_length; // // Méthodes d'extraction : - descrScanner descrRange() const - {return descrScanner(this+1, PUINT8(this+1) + dloop_length());} - const SI_SDT_entry * next() const - {return reinterpret_cast(PUINT8(this+1) + dloop_length());} + descrScanner descrRange() const { + return descrScanner(this+1, PUINT8(this+1) + dloop_length());} + const SI_SDT_entry * next() const { + return reinterpret_cast(PUINT8(this+1) + dloop_length());} }; // SDT = Service Description Table @@ -2968,10 +2996,10 @@ UINT8 reserved; // // Méthodes d'extraction : - UINT16 tsid(bool microsoft=false) const - {return section_id(microsoft);} - streamScanner entryRange(bool microsoft=false) const - {return streamScanner(this+1, end(microsoft));} + UINT16 tsid(bool microsoft=false) const { + return section_id(microsoft);} + streamScanner entryRange(bool microsoft=false) const { + return streamScanner(this+1, end(microsoft));} }; // ############################################################################ @@ -3019,10 +3047,10 @@ UBE16 onid; LEN12 dloop_length; // - descrScanner descrRange() const - {return descrScanner(this+1, PUINT8(this+1) + dloop_length());} - const SI_NIT_entry * next() const - {return reinterpret_cast(PUINT8(this+1) + dloop_length());} + descrScanner descrRange() const { + return descrScanner(this+1, PUINT8(this+1) + dloop_length());} + const SI_NIT_entry * next() const { + return reinterpret_cast(PUINT8(this+1) + dloop_length());} }; /// En-tête de la seconde partie d'une table SI_NIT @@ -3030,8 +3058,8 @@ { LEN12 eloop_length; // - streamScanner entryRange() const - {return streamScanner(this+1, PUINT8(this+1) + eloop_length());} + streamScanner entryRange() const { + return streamScanner(this+1, PUINT8(this+1) + eloop_length());} }; /// Représentation table PSI : NIT = Network Information Table @@ -3039,12 +3067,12 @@ { LEN12 dloop_length; // - UINT16 network_id(bool microsoft=false) const - {return section_id(microsoft);} - descrScanner descrRange() const - {return descrScanner(this+1, PUINT8(this+1) + dloop_length());} - const SI_NIT_entries_hdr & entries_hdr() const - {return *reinterpret_cast(PUINT8(this+1) + dloop_length());} + UINT16 network_id(bool microsoft=false) const { + return section_id(microsoft);} + descrScanner descrRange() const { + return descrScanner(this+1, PUINT8(this+1) + dloop_length());} + const SI_NIT_entries_hdr & entries_hdr() const { + return *reinterpret_cast(PUINT8(this+1) + dloop_length());} }; // ############################################################################ @@ -3098,8 +3126,8 @@ { BYTE b; - BYTE operator() () const - {return (b>>4)*10 + (b & 0x0f);} + BYTE operator() () const { + return (b>>4)*10 + (b & 0x0f);} }; /// Représentation de l'heure sous forme de trois octets de type BCD @@ -3109,8 +3137,8 @@ BCD8 m; BCD8 s; - operator UINT32() const - {return ((h()*60+m())*60+s())*1000;} // Résultat en millisecondes + operator UINT32() const { + return ((h()*60+m())*60+s())*1000;} // Résultat en millisecondes }; /// Représentation d'une date compactée sur 16 bits "big endian" @@ -3136,8 +3164,8 @@ MJD16 day; TIM24 time; - UINT64 operator () () const - {return UINT64(day*24*60*60) + time;} // Conversion en secondes + UINT64 operator () () const { + return UINT64(day)*24*60*60*1000 + time;} // Conversion en millisecondes operator SYSTEMTIME () const { SYSTEMTIME st; @@ -3160,14 +3188,14 @@ TIM24 duration; LEN12 dloop_length; - UINT8 running_status() const - {return UINT8(dloop_length.flags()>>5);} - UINT8 free_CA_mode() const - {return UINT8((dloop_length.flags()>>4)&0x01);} - descrScanner descrRange() const - {return descrScanner(this+1, PUINT8(this+1) + dloop_length());} - const SI_EIT_entry * next() const - {return reinterpret_cast(PUINT8(this+1) + dloop_length());} + UINT8 running_status() const { + return UINT8(dloop_length.flags()>>5);} + UINT8 free_CA_mode() const { + return UINT8((dloop_length.flags()>>4)&0x01);} + descrScanner descrRange() const { + return descrScanner(this+1, PUINT8(this+1) + dloop_length());} + const SI_EIT_entry * next() const { + return reinterpret_cast(PUINT8(this+1) + dloop_length());} }; /// Représentation table PSI : EIT = Event Information Table @@ -3178,10 +3206,10 @@ UINT8 segment_last_section_number; UINT8 last_table_id; - UINT16 service_id(bool microsoft=false) const - {return section_id(microsoft);} - streamScanner entryRange(bool microsoft=false) const - {return streamScanner(this+1, end(microsoft));} + UINT16 service_id(bool microsoft=false) const { + return section_id(microsoft);} + streamScanner entryRange(bool microsoft=false) const { + return streamScanner(this+1, end(microsoft));} SI_EIT_subtype getSubtype() const { Modifié: trunk/parse.cpp =================================================================== --- trunk/parse.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/parse.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -196,18 +196,18 @@ // Classe de soutien à la lecture des tables TS class Mpeg2SectionsHandler { - PID _pid; - TID _tid; - DWORD _dwTimeout; - ISectionList * pSectionList; - MPEG2_FILTER filter; - IF_DEBUG(FOURCC tableName;) - BYTE nextSection; - BYTE lastSection; + PID _pid; + TID _tid; + DWORD _dwTimeout; + CComPtr pSectionList; + MPEG2_FILTER filter; + IF_DEBUG(FOURCC tableName;) + BYTE nextSection; + BYTE lastSection; public: - PSECTION data; - DWORD length; - bool complete; // true si toute la table a été lue avec succès + PSECTION data; + DWORD length; + bool complete; //!< true si toute la table a été lue avec succès // void Init(PID pid, TID tid, DWORD dwTimeout, FOURCC tblName); bool GetNextSection(); @@ -235,13 +235,11 @@ bool Mpeg2SectionsHandler::GetNextSection() { HRESULT hr; - // + // Libération de la section précédemment chargée : - if (pSectionList && length>0) { - pSectionList->Release(); - length = 0; - } - // + pSectionList.Release(); + length = 0; + if (nextSection>lastSection) { complete = true; return false; Modifié: trunk/record.cpp =================================================================== --- trunk/record.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/record.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -33,8 +33,24 @@ #include "grabber.h" #include "capture.h" -Enregistrement enregistrements_actuels[NB_MAX_ENREG]; +/** + * Table des enregistrements d'émissions en cours de traitement + * (parfois dénommés "grabbers" en raison de l'usage d'un filtre + * "Sample grabber" pour chacun de ces enregistrements) + **/ +Enregistrement enregistrements_actuels[NB_MAX_ENREG]; +/** + * Démarrage d'un enregistrement. + * \param[in] pCallback Pointeur sur un objet dérivé de \p ISampleGrabberCB, implémentant les + * méthode "callback" nécessaires à la récupération des échantillons + * à enregistrer + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne à enregistrer, ou bien + * \p STREAM_PSEUDO_INDEX pour spécifier tout le multiplex + * \param[in] pProg Pointeur facultatif sur la programmation horaire ayant servi à démarrer + * l'enregistrement : s'il n'est pas \p NULL, des paramètres additionnels + * y sont récupérés + **/ void Enregistrement::start(ISampleGrabberCB * pCallback, int ixChaine, Programme * pProg) { WORD sidCh = indexToSID(ixChaine); @@ -51,32 +67,46 @@ } } -// Prise en compte d'une programmation affectant une chaîne déjà en cours d'enregistrement +/** + * Prise en compte d'une programmation affectant une chaîne déjà en cours d'enregistrement. + * Cette fonction est appelée dans le cas où un enregistrement programmé doit démarrer, et + * qu'il est constaté que la chaîne correspondante a déjà un enregistrement en cours. + * \param[in] pProg Pointeur sur la programmation horaire ayant servi à démarrer + * l'enregistrement + * \retval \p true si succès + * \retval \p false si une incompatibilité est rencontrée : la programmation demande + * une méthode d'enregistrement ou une piste audio qui diffèrent de celles de + * l'enregistrement en cours ; dans ce cas, l'enregistrement est mis en erreur + **/ bool Enregistrement::modify_prog(Programme * pProg) { if (pProg && DiffTime(pProg->fin, fin)>0) { programmation_modifiee = true; if (pProg->methode!=methode || pProg->audio!=audio) { - pProg->etat = epr_erreur; // état de la nouvelle programmation utilisée + // Incompatibilité : la programmation demande une méthode d'enregistrement ou une + // piste audio qui diffèrent de celles de l'enregistrement en cours + pProg->etat = epr_erreur; // état de la nouvelle programmation utilisée return false; - } else { - int ixProg = trouve_prog_par_nom(nom); + } - if (ixProg>=0) - Programmes[ixProg].etat = epr_supplante; // état de l'ancienne programmation utilisée + int ixProg = trouve_prog_par_nom(nom); - fin = pProg->fin; - apres = pProg->apres; - pProg->etat = epr_encours; // état de la nouvelle programmation utilisée - strcpy_T(nom, pProg->nom); - } + if (ixProg>=0) + Programmes[ixProg].etat = epr_supplante; // état de l'ancienne programmation utilisée + + fin = pProg->fin; + apres = pProg->apres; + pProg->etat = epr_encours; // état de la nouvelle programmation utilisée + strcpy_T(nom, pProg->nom); } return true; } /** - * Arrêt de l'enregistrement. Retourne l'action à effectuer ensuite, - * ou bien 'apr_null' si l'enregistrement n'était pas en cours. + * Arrêt de l'enregistrement. + * \param[in] raison Raison de l'arrêt (état de programmation suivant) + * \retval Action à effectuer ensuite + * \retval \p apr_null si l'enregistrement n'était pas en cours. **/ ApresEnregistrement Enregistrement::stop(EtatProgramme raison) { @@ -119,7 +149,10 @@ } /** - * Obtenir le nom de la chaîne enregistrée (retourne un "*" s'il s'agit du multiplex entier) + * Obtenir le nom de la chaîne enregistrée (retourne un "*" s'il s'agit du multiplex entier) : + * \retval Pointeur sur le nom de la chaîne + * \retval "*" S'il s'agit du multiplex entier + * \retval "??" (erreur interne) **/ LPCSTR Enregistrement::channelName() const { @@ -134,8 +167,9 @@ } /** - * Calcul du temps restant avant fin enregistrement en millisecondes. - * L'heure de référence (en principe l'heure système) doit être passée en paramètre. + * Calcul du temps restant avant la fin de l'enregistrement. + * \param[in] localtime Heure de référence (en principe l'heure système) + * \retval Temps restant, en millisecondes **/ long Enregistrement::temps_restant(const SYSTEMTIME & localtime) const { @@ -151,7 +185,8 @@ /** * Détermine si on enregistre actuellement * - * Renvoie le SID de la première chaîne enregistrée trouvée si on enregistre actuellement, 0 sinon + * \retval SID de la première chaîne enregistrée trouvée + * \retval 0 si aucun enregistrement n'est en cours. **/ WORD recording() { @@ -174,9 +209,12 @@ } /** - * Chercher l'index (dans 'enregistrements_actuels') des informations concernant - * la chaîne d'index 'ixChaine' si celle-ci est en cours d'enregistrement. - * Retourne -1 si elle ne l'est pas. + * Rechercher si une chaîne est en cours d'enregistrement, + * et si oui, obtenir l'index des informations concernant cet enregistrement. + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne concernée, ou bien + * \p STREAM_PSEUDO_INDEX pour spécifier tout le multiplex courant + * \retval Index de l'enregistrement ("grabber") dans la table #enregistrements_actuels + * \retval -1 si la chaîne n'est pas en cours d'enregistrement. **/ int getGrabberChaine(int ixChaine) { @@ -192,8 +230,9 @@ } /** - * Chercher un index d'enregistrement libre dans 'enregistrements_actuels'. - * Retourne l'index de ce poste, ou bien -1 s'il n'y en a plus de disponible. + * Chercher un index d'enregistrement libre ("grabber") + * \retval Index de l'enregistrement dans la table #enregistrements_actuels + * \retval -1 si tous les index possibles sont utilisés. **/ int getFreeGrabber() { @@ -217,15 +256,14 @@ } /** - * Démarrage d'un enregistrement en mode TS, pour la chaîne dont l'index est égal à ixChaine. + * Démarrage d'un enregistrement en mode TS. * Le tuner est supposé être déjà syntonisé sur la bonne fréquence. - * Toutes les pistes audio sont enregistrées. - * 'pProg' est un pointeur facultatif sur la programmation horaire ayant servi à démarrer - * l'enregistrement : s'il n'est pas NULL, des paramètres additionnels y sont récupérés. - * Retourne l'index dans la table des enregistrements, ou bien -1 si aucun enregistrement n'a pu démarrer. - * TODO : retirer la restriction sur la syntonisation - * TODO : ajouter le paramètre 'ixSon' pour choisir entre l'enregistrement d'une piste audio donnée, - * ou bien toutes les pistes audio si -1 + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne à enregistrer + * \param[in] pProg Pointeur facultatif sur la programmation horaire ayant servi à démarrer + * l'enregistrement : s'il n'est pas \p NULL, des paramètres additionnels + * y sont récupérés + * \retval Index de l'enregistrement ("grabber") dans la table #enregistrements_actuels + * \retval -1 si aucun enregistrement n'a pu démarrer. **/ int start_record_ts(int ixChaine, Programme * pProg) { @@ -260,14 +298,15 @@ } /** - * Démarrage d'un enregistrement en mode PS, pour la chaîne dont l'index. - * est égal à 'ixChaine', avec 'ixSon' comme piste son. + * Démarrage d'un enregistrement en mode PS. * Le tuner est supposé être déjà syntonisé sur la bonne fréquence. - * 'pProg' est un pointeur facultatif sur la programmation horaire ayant servi à démarrer - * l'enregistrement : s'il n'est pas NULL, des paramètres additionnels y sont récupérés. - * Retourne l'index dans la table des enregistrements, ou bien -1 si aucun enregistrement n'a pu démarrer. - * TODO : retirer la restriction sur la syntonisation - * TODO : faire en sorte que toutes les pistes son soient enregistrées si 'ixSon'=-1 + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne à enregistrer + * \param[in] ixSon Index de la piste audio dans la table \p sons de cette chaîne + * \param[in] pProg Pointeur facultatif sur la programmation horaire ayant servi à démarrer + * l'enregistrement : s'il n'est pas \p NULL, des paramètres additionnels + * y sont récupérés + * \retval Index de l'enregistrement ("grabber") dans la table #enregistrements_actuels + * \retval -1 si aucun enregistrement n'a pu démarrer. **/ int start_record_ps(int ixChaine, int ixSon, Programme * pProg) { @@ -307,11 +346,11 @@ /** * Démarrage d'un enregistrement global du multiplex. - * Retourne l'index dans la table des enregistrements, ou bien -1 si aucun enregistrement n'a pu démarrer. - * 'pProg' est un pointeur facultatif sur la programmation horaire ayant servi à démarrer - * l'enregistrement : s'il n'est pas NULL, des paramètres additionnels y sont récupérés. - * TODO : ajouter un paramètre (par ex. ixChaine) pour que soit préalablement syntonisé le multiplex - * correspondant à la chaîne désignée. + * \param[in] pProg Pointeur facultatif sur la programmation horaire ayant servi à démarrer + * l'enregistrement : s'il n'est pas \p NULL, des paramètres additionnels + * y sont récupérés + * \retval Index de l'enregistrement ("grabber") dans la table #enregistrements_actuels + * \retval -1 si aucun enregistrement n'a pu démarrer. **/ int start_record_stream(Programme * pProg) { Modifié: trunk/record.h =================================================================== --- trunk/record.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/record.h 2009-01-30 21:00:14 UTC (rev 170) @@ -29,53 +29,109 @@ #include "recprog.h" -// Durée maximale qui sépare deux appels au timer de début d'enregistrement. -// Si le temps avant l'enregistrement suivant est plus long que ce délai, -// le timer est programmé sur cette valeur, et est donc de fait recalculé -// à intervalles identiques à cette valeur jusqu'à ce que la durée restante -// soit inférieure. +/** + * Durée maximale qui sépare deux appels au timer de début d'enregistrement. + * Si le temps avant l'enregistrement suivant est plus long que ce délai, + * le timer est programmé sur cette valeur, et est donc de fait recalculé + * à intervalles identiques à cette valeur jusqu'à ce que la durée restante + * soit inférieure. + **/ #if _DEBUG #define DUREE_RECALCUL_TIMERS 10 // Valeur en secondes #else #define DUREE_RECALCUL_TIMERS (10*60) // Valeur en secondes #endif +/// Description d'un enregistrement (capture) de chaîne qui est en cours de traitement class Enregistrement : public RecordInfo { public: CComPtr pSample; - // - // Mini-constructeur : + + /// Constructeur Enregistrement() {} - // - bool recording() const {return sidChaine >0;} - bool isChannel(WORD sidCh) const {return sidChaine == sidCh;} + /// Déterminer si cet enregistrement de chaîne est couramment actif + bool recording() const { + return sidChaine >0;} + + /// Déterminer si cet enregistrement de chaîne correspond au SID \p sidCh, donné en paramètre + bool isChannel(WORD sidCh) const { + return sidChaine == sidCh;} + + /** + * Démarrage d'un enregistrement. + * \param[in] pCallback Pointeur sur un objet dérivé de \p ISampleGrabberCB, implémentant les + * méthode "callback" nécessaires à la récupération des échantillons + * à enregistrer + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne à enregistrer, ou bien + * \p STREAM_PSEUDO_INDEX pour spécifier tout le multiplex + * \param[in] pProg Pointeur facultatif sur la programmation horaire ayant servi à démarrer + * l'enregistrement : s'il n'est pas \p NULL, des paramètres additionnels + * y sont récupérés + **/ void start(ISampleGrabberCB * pCallback, int ixChaine, Programme * pProg); - // Prise en compte d'une programmation affectant une chaîne déjà en cours d'enregistrement + /** + * Prise en compte d'une programmation affectant une chaîne déjà en cours d'enregistrement. + * Cette fonction est appelée dans le cas où un enregistrement programmé doit démarrer, et + * qu'il est constaté que la chaîne correspondante a déjà un enregistrement en cours. + * \param[in] pProg Pointeur sur la programmation horaire ayant servi à démarrer + * l'enregistrement + * \retval \p true si succès + * \retval \p false si une incompatibilité est rencontrée : la programmation demande + * une méthode d'enregistrement ou une piste audio qui diffèrent de celles de + * l'enregistrement en cours ; dans ce cas, l'enregistrement est mis en erreur + * \todo Faire en sorte qu'une incompatibilité ne provoque pas d'erreur, mais à la place, + * amène l'arrêt de l'enregistrement en cours suivi immédiatement du démarrage d'un nouvel + * enregistrement utilisant les nouveaux paramètres + **/ bool modify_prog(Programme * pProg); + /// Obtenir l'interface du "Sample grabber" void query(CComPtr & pGrabber); + + /// Libérer l'interface du "Sample grabber" void release(); - // Calcul du temps restant avant fin enregistrement en millisecondes. - // L'heure de référence (en principe l'heure système) doit être passée en paramètre. + /** + * Calcul du temps restant avant la fin de l'enregistrement. + * \param[in] localtime Heure de référence (en principe l'heure système) + * \retval Temps restant, en millisecondes + **/ long temps_restant(const SYSTEMTIME & localtime) const; - // Arrêt de l'enregistrement. Retourne l'action à effectuer ensuite, - // ou bien 'apr_null' si l'enregistrement n'était pas en cours. + /** + * Arrêt de l'enregistrement. + * \param[in] raison Raison de l'arrêt (état de programmation suivant) + * \retval Action à effectuer ensuite + * \retval \p apr_null si l'enregistrement n'était pas en cours. + **/ ApresEnregistrement stop(EtatProgramme raison); - // Obtenir le nom de la chaîne enregistrée (retourne un "*" s'il s'agit du multiplex entier) : + /** + * Obtenir le nom de la chaîne enregistrée (retourne un "*" s'il s'agit du multiplex entier) : + * \retval Pointeur sur le nom de la chaîne + * \retval "*" S'il s'agit du multiplex entier + * \retval "??" (erreur interne) + **/ LPCSTR channelName() const; }; -extern Enregistrement enregistrements_actuels[NB_MAX_ENREG]; +/** + * Table des enregistrements d'émissions en cours de traitement + * (parfois dénommés "grabbers" en raison de l'usage d'un filtre + * "Sample grabber" pour chacun de ces enregistrements) + * \todo Ne plus utiliser un filtre "Sample grabber" pour chacun + * de ces enregistrements, un seul filtre suffit pour tous. + * Concommittamment, changer les appellations "grabber" utilisées. + **/ +extern Enregistrement enregistrements_actuels[NB_MAX_ENREG]; /** * Détermine si on enregistre actuellement * - * Renvoie le SID de la première chaîne enregistrée trouvée si on enregistre actuellement, 0 sinon + * \retval SID de la première chaîne enregistrée trouvée + * \retval 0 si aucun enregistrement n'est en cours. **/ WORD recording(); @@ -85,52 +141,62 @@ void stop_all_records(); /** - * Chercher l'index (dans 'enregistrements_actuels') des informations concernant - * la chaîne d'index 'ixChaine' si celle-ci est en cours d'enregistrement. - * Retourne -1 si elle ne l'est pas. + * Rechercher si une chaîne est en cours d'enregistrement, + * et si oui, obtenir l'index des informations concernant cet enregistrement. + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne concernée, ou bien + * \p STREAM_PSEUDO_INDEX pour spécifier tout le multiplex courant + * \retval Index de l'enregistrement ("grabber") dans la table #enregistrements_actuels + * \retval -1 si la chaîne n'est pas en cours d'enregistrement. **/ int getGrabberChaine(int ixChaine); /** - * Chercher un index d'enregistrement libre dans 'enregistrements_actuels'. - * Retourne l'index de ce poste, ou bien -1 s'il n'y en a plus de disponible. + * Chercher un index d'enregistrement libre ("grabber") + * \retval Index de l'enregistrement dans la table #enregistrements_actuels + * \retval -1 si tous les index possibles sont utilisés. **/ int getFreeGrabber(); /** - * Démarrage d'un enregistrement en mode TS, pour la chaîne dont l'index est égal à ixChaine. + * Démarrage d'un enregistrement en mode TS. * Le tuner est supposé être déjà syntonisé sur la bonne fréquence. - * Toutes les pistes audio sont enregistrées. - * 'pProg' est un pointeur facultatif sur la programmation horaire ayant servi à démarrer - * l'enregistrement : s'il n'est pas NULL, des paramètres additionnels y sont récupérés. - * Retourne l'index dans la table des enregistrements, ou bien -1 si aucun enregistrement n'a pu démarrer. - * TODO : retirer la restriction sur la syntonisation - * TODO : ajouter le paramètre 'ixSon' pour choisir entre l'enregistrement d'une piste audio donnée, - * ou bien toutes les pistes audio si -1 + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne à enregistrer + * \param[in] pProg Pointeur facultatif sur la programmation horaire ayant servi à démarrer + * l'enregistrement : s'il n'est pas \p NULL, des paramètres additionnels + * y sont récupérés + * \retval Index de l'enregistrement ("grabber") dans la table #enregistrements_actuels + * \retval -1 si aucun enregistrement n'a pu démarrer. + * \todo Retirer la restriction sur la syntonisation, et ajouter le paramètre \p ixSon + * pour choisir de n'enregistrer qu'une seule piste audio, si ce paramètre n'est pas -1. **/ int start_record_ts(int ixChaine, Programme * pProg=NULL); /** - * Démarrage d'un enregistrement en mode PS, pour la chaîne dont l'index. - * est égal à 'ixChaine', avec 'ixSon' comme piste son. + * Démarrage d'un enregistrement en mode PS. * Le tuner est supposé être déjà syntonisé sur la bonne fréquence. - * 'pProg' est un pointeur facultatif sur la programmation horaire ayant servi à démarrer - * l'enregistrement : s'il n'est pas NULL, des paramètres additionnels y sont récupérés. - * Retourne l'index dans la table des enregistrements, ou bien -1 si aucun enregistrement n'a pu démarrer. - * TODO : retirer la restriction sur la syntonisation - * TODO : faire en sorte que toutes les pistes son soient enregistrées si 'ixSon'=-1 + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne à enregistrer + * \param[in] ixSon Index de la piste audio dans la table \p sons de cette chaîne + * \param[in] pProg Pointeur facultatif sur la programmation horaire ayant servi à démarrer + * l'enregistrement : s'il n'est pas \p NULL, des paramètres additionnels + * y sont récupérés + * \retval Index de l'enregistrement ("grabber") dans la table #enregistrements_actuels + * \retval -1 si aucun enregistrement n'a pu démarrer. + * \todo Retirer la restriction sur la syntonisation, et faire en sorte que toutes + * les pistes son soient enregistrées si \p ixSon = -1 **/ int start_record_ps(int ixChaine, int ixSon, Programme * pProg=NULL); -#define STREAM_PSEUDO_SID 0xffff // Pseudo SID pour l'enregistrement du multiplex -#define STREAM_PSEUDO_INDEX -2 // Pseudo index de chaîne pour l'enregistrement du multiplex +#define STREAM_PSEUDO_SID 0xffff //!< Pseudo SID pour l'enregistrement du multiplex +#define STREAM_PSEUDO_INDEX -2 //!< Pseudo index de chaîne pour l'enregistrement du multiplex /** * Démarrage d'un enregistrement global du multiplex. - * Retourne l'index dans la table des enregistrements, ou bien -1 si aucun enregistrement n'a pu démarrer. - * 'pProg' est un pointeur facultatif sur la programmation horaire ayant servi à démarrer - * l'enregistrement : s'il n'est pas NULL, des paramètres additionnels y sont récupérés. - * TODO : ajouter un paramètre (par ex. ixChaine) pour que soit préalablement syntonisé le multiplex - * correspondant à la chaîne désignée. + * \param[in] pProg Pointeur facultatif sur la programmation horaire ayant servi à démarrer + * l'enregistrement : s'il n'est pas \p NULL, des paramètres additionnels + * y sont récupérés + * \retval Index de l'enregistrement ("grabber") dans la table #enregistrements_actuels + * \retval -1 si aucun enregistrement n'a pu démarrer. + * \todo Ajouter un paramètre (par ex. \p ixChaine) pour que soit préalablement syntonisé + * le multiplex correspondant à la chaîne désignée. **/ int start_record_stream(Programme * pProg=NULL); Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/recprog.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -196,9 +196,9 @@ AddTime(debut, to_add); AddTime(fin, to_add); - // TODO : il faudrait vérifier d'une façon ou d'une autre qu'une transition - // heure d'été <-> heure d'hiver intempestive ne risque pas d'introduire un - // décalage d'une heure dans la programmation à cet endroit. + /// \todo Il faudrait vérifier d'une façon ou d'une autre qu'une transition + /// heure d'été <-> heure d'hiver intempestive ne risque pas d'introduire un + /// décalage d'une heure dans la programmation à cet endroit. etat = epr_actif; // réactivation programmation_modifiee = true; @@ -857,8 +857,9 @@ GetCtlTimeDate(hDlg, IDC_DATE_START, IDC_TIME_START, prog.debut); GetCtlTimeDate(hDlg, IDC_DATE_END, IDC_TIME_END, prog.fin); - prog.methode = (MethodeEnregistrement)SendDlgItemMessage(hDlg, IDC_METHOD, CB_GETCURSEL, 0, 0); - prog.audio = (AudioMode)SendDlgItemMessage(hDlg, IDC_AUDIO, CB_GETCURSEL, 0, 0); + // Ces deux valeurs ont été extraites de la boîte de dialogue au moment de leur sélection : + prog.methode = epg_typerecvideo; + prog.audio = epg_typerecaudio; const Chaine & canal = Canaux[ixChaine]; NomProg nom; @@ -924,6 +925,9 @@ /** * Transfert d'une description d'émission dans une structure d'enregistrement programmé + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne concernée + * \param[in] noEmis Numéro de l'émission (0 ou 1) dans la liste des émissions de cette chaîne + * \param[out] prog Structure recevant la description **/ bool chaineToProg(int ixChaine, BYTE noEmis, Programme & prog) { @@ -969,11 +973,8 @@ SetCtlTimeDate(hDlg, IDC_DATE_START, IDC_TIME_START, dtc_debut = localtime); SetCtlTimeDate(hDlg, IDC_DATE_END, IDC_TIME_END, dtc_fin = localtime); CtlSelChannel(GetDlgItem(hDlg, IDC_CHANNEL), ixChaineCourante); - SendDlgItemMessage(hDlg, IDC_METHOD, CB_SETCURSEL, meth_TS, 0); - SendDlgItemMessage(hDlg, IDC_AUDIO, CB_SETCURSEL, audio_1, 0); - SendDlgItemMessage(hDlg, IDC_NAME, WM_SETTEXT, 0, (LPARAM)L""); + SendDlgItemMessage(hDlg, IDC_NAME, WM_SETTEXT, 0, (LPARAM)TEXT("")); - EnableWindow(GetDlgItem(hDlg, IDC_AUDIO), FALSE); SetCtlAfter(hDlg, IDC_AFTER_POWEROFF, IDC_AFTER, apr_rien); CheckDlgButton(hDlg, IDC_TACHE, BST_UNCHECKED); CheckDlgButton(hDlg, IDC_INACTIVE, BST_UNCHECKED); @@ -1031,6 +1032,41 @@ SendMessage(hCtl, CB_SETCURSEL, audio_1, 0); } +/** + * Initialisation des items de méthodes d'enregistrement d'un dialogue d'enregistrements programmés + * \param[in] hDlg "Handle" de la boîte de dialogue + **/ +void init_methodes(HWND hDlg) +{ + HWND hCtlMtd = GetDlgItem(hDlg, IDC_METHOD); + HWND hCtlAud = GetDlgItem(hDlg, IDC_AUDIO); + + remplit_liste_methodes(hCtlMtd); + remplit_liste_audio(hCtlAud); + + // Sélectionne le dernier paramètre utilisé pour l'enregistrement + SendMessage(hCtlMtd, CB_SETCURSEL, epg_typerecvideo, NULL); + SendMessage(hCtlAud, CB_SETCURSEL, epg_typerecaudio, NULL); + + EnableWindow(hCtlAud, epg_typerecvideo == meth_PS); +} + +/** + * Mise à jour des méthodes d'enregistrement après changement d'un des items de dialogue + * qui les contrôlent + * \param[in] hDlg "Handle" de la boîte de dialogue + **/ +void update_methodes(HWND hDlg) +{ + HWND hCtlMtd = GetDlgItem(hDlg, IDC_METHOD); + HWND hCtlAud = GetDlgItem(hDlg, IDC_AUDIO); + + epg_typerecvideo = (MethodeEnregistrement)SendMessage(hCtlMtd, CB_GETCURSEL, 0, NULL); + epg_typerecaudio = (AudioMode)SendMessage(hCtlAud, CB_GETCURSEL, 0, NULL); + + EnableWindow(hCtlAud, epg_typerecvideo == meth_PS); +} + static void update_edit_state(HWND hDlg, int selection) { NomProg nom; @@ -1071,9 +1107,7 @@ ListView_AjouteColonnes(hListItem, t_cols); remplit_liste_programmes(hListItem); remplit_liste_chaines(GetDlgItem(hDlg, IDC_CHANNEL)); // Chargement du combo de choix des chaînes - remplit_liste_methodes(GetDlgItem(hDlg, IDC_METHOD)); - remplit_liste_audio(GetDlgItem(hDlg, IDC_AUDIO)); - + init_methodes(hDlg); InitNewRecord(hDlg); update_edit_state(hDlg, selection); ShowCursor(TRUE); // Suspend la disparition temporisée du curseur @@ -1093,18 +1127,15 @@ dtc_debut = prog.debut; dtc_fin = prog.fin; - SendDlgItemMessage(hDlg, IDC_METHOD, CB_SETCURSEL, prog.methode, 0); - SendDlgItemMessage(hDlg, IDC_AUDIO, CB_SETCURSEL, prog.audio, 0); + SendDlgItemMessage(hDlg, IDC_METHOD, CB_SETCURSEL, epg_typerecvideo = prog.methode, NULL); + SendDlgItemMessage(hDlg, IDC_AUDIO, CB_SETCURSEL, epg_typerecaudio = prog.audio, NULL); + EnableWindow(GetDlgItem(hDlg, IDC_AUDIO), epg_typerecvideo == meth_PS); SetCtlAfter(hDlg, IDC_AFTER_POWEROFF, IDC_AFTER, prog.apres); CheckDlgButton(hDlg, IDC_TACHE, prog.tache!=planif_sans ? BST_CHECKED : BST_UNCHECKED); - // Active ou désactive le choix des pistes audio - PostMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_METHOD, CBN_SELCHANGE), - LPARAM(GetDlgItem(hDlg, IDC_METHOD))); - // Coche les cases pour les répétitions : SetCtlRepeat(hDlg, IDC_REP_BASE, prog.repetition); @@ -1144,9 +1175,9 @@ switch(LOWORD(wParam)) { case IDC_METHOD: + case IDC_AUDIO: if (HIWORD(wParam) == CBN_SELCHANGE) { - EnableWindow(GetDlgItem(hDlg, IDC_AUDIO), - SendDlgItemMessage(hDlg, IDC_METHOD, CB_GETCURSEL, 0, 0)==meth_PS); + update_methodes(hDlg); return TRUE; } break; @@ -1782,13 +1813,9 @@ } else { // Il n'y avait pas d'autre enregistrement en cours frequence_courante = canal.khz; - if (!ixChaine_ok(ixChaineCourante) || frequence_courante != Canaux[ixChaineCourante].khz) { - // On syntonise maintenant si on n'était pas déjà syntonisé sur ce multiplex - ixChaineCourante = -1; // doit être égal à -1 pendant les transitions - change_frequence(frequence_courante); - ixChaineCourante = ixChaine; - ixSonCourant = 0; - } + if (!ixChaine_ok(ixChaineCourante) || frequence_courante != Canaux[ixChaineCourante].khz) + // On change de chaîne, seulement si le multiplex est différent + zappe_index(ixChaine); } if (!IsMinimized(hMainWnd) && suspend_minimized) Modifié: trunk/recprog.h =================================================================== --- trunk/recprog.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/recprog.h 2009-01-30 21:00:14 UTC (rev 170) @@ -30,14 +30,7 @@ #include "base.h" #include "ini.h" -/// Spécification de la méthode d'enregistrement -enum MethodeEnregistrement { - meth_TS, //!< 0: L'enregistrement s'effectuera en mode TS - meth_PS, //!< 1: L'enregistrement s'effectuera en mode PS - meth_multiplex //!< 2: Le multiplex entier sera enregistré -}; - -/// Indique quoi faire après un enregitrement +/// Indique quoi faire après un enregistrement enum ApresEnregistrement { apr_null = -1, //!< -1: Utilisé dans les enregistrements en cours, pour indiquer //!< qu'aucun horaire de fin n'est associé à un enregistrement @@ -46,13 +39,6 @@ apr_eteindrePC, //!< 2: On quitte l'application et on éteint l'ordinateur }; -/// Indique quelle piste audio sera utilisée dans un enregistrement -enum AudioMode { - audio_1, //!< Utilisation de la première piste MPEG2 disponible - audio_2, //!< Utilisation de la seconde piste MPEG2 disponible - audio_AC3 //!< Utilisation de la première piste AC3 disponible -}; - /// Statut d'un enregistrement par rapport au planificateur de tâches enum PlanificateurTache { planif_sans, //!< 0: non planifiée @@ -74,17 +60,17 @@ typedef TCHAR NomProg[64]; //!< Type pour nom donné à une programmation -// Structure commune aux programmations d'enregistrement et aux enregistrements en cours : +/// Structure commune aux programmations d'enregistrement et aux enregistrements en cours class RecordInfo { public: - NomProg nom; // Nom de la programmation si applicable - WORD sidChaine; // SID de la chaîne enregistrée - WORD numeroChaine; // Numéro de la chaîne - ApresEnregistrement apres; - MethodeEnregistrement methode; - AudioMode audio; - SYSTEMTIME fin; // Date & heure de fin + NomProg nom; //!< Nom de la programmation si applicable + WORD sidChaine; //!< SID de la chaîne enregistrée + WORD numeroChaine; //!< Numéro de la chaîne + ApresEnregistrement apres; //!< Quoi faire après la fin de l'enregistrement + MethodeEnregistrement methode; //!< Méthode d'enregistrement (TS, PS, Multiplex) + AudioMode audio; //!< Mode audio utilisé / à utiliser + SYSTEMTIME fin; //!< Date & heure de fin // Mini-constructeur : RecordInfo() {memset(this, 0, sizeof(*this)); apres = apr_null;} @@ -239,8 +225,6 @@ **/ void record_list_updated(); -//void do_record_stop(int grab); - /** * Exécution de toutes les transitions d'enregistrements (démarrage, * arrêt, erreur...) qui devraient être assurées à cet instant. @@ -251,6 +235,9 @@ /** * Transfert d'une description d'émission dans une structure d'enregistrement programmé + * \param[in] ixChaine Index (dans la table #Canaux) de la chaîne concernée + * \param[in] noEmis Numéro de l'émission (0 ou 1) dans la liste des émissions de cette chaîne + * \param[out] prog Structure recevant la description **/ bool chaineToProg(int ixChaine, BYTE noEmis, Programme & prog); @@ -265,10 +252,25 @@ /** * Remplissage d'une combo-box de méthodes d'enregistement + * \param[in] hCtl "Handle" de la combo-box **/ void remplit_liste_methodes(HWND hCtl); /** * Remplissage d'une combo-box d'items audio + * \param[in] hCtl "Handle" de la combo-box **/ -void remplit_liste_audio(HWND hCtl); \ Pas de fin de ligne à la fin du fichier +void remplit_liste_audio(HWND hCtl); + +/** + * Initialisation des items de méthodes d'enregistrement d'un dialogue d'enregistrements programmés + * \param[in] hDlg "Handle" de la boîte de dialogue + **/ +void init_methodes(HWND hDlg); + +/** + * Mise à jour des méthodes d'enregistrement après changement d'un des items de dialogue + * qui les contrôlent + * \param[in] hDlg "Handle" de la boîte de dialogue + **/ +void update_methodes(HWND hDlg); Modifié: trunk/rendering.cpp =================================================================== --- trunk/rendering.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/rendering.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -245,35 +245,38 @@ /// Provoquer l'affichage du contenu du rectangle. Cette fonction est appelée /// par \p SetText, mais peut aussi être utilisée pour rafraîchir un affichage /// déjà établi. -void COsdObject::Draw() +/// \param[in] bLast \p true si cet affichage est le dernier d'un groupe d'affichages simultanés +void COsdObject::Draw(bool bLast) { if (nTextSize) { if (pVMR) // si le VMR existe, on lui délègue la tâche (même si on // sait qu'il va peut-être nous la réassigner) - pVMR->DrawOsdText(*this, false); + pVMR->DrawOsdText(*this, false, bLast); else DoInvalidate(); } } -/// Effacement (temporaire) d'un texte existant dans le rectanble OSD. -void COsdObject::Hide() +/// Effacement (temporaire) d'un texte existant dans le rectangle OSD. +/// \param[in] bLast \p true si cet effacement est le dernier d'un groupe d'effacements simultanés +void COsdObject::Hide(bool bLast) { if (nTextSize) { if (pVMR) // si le VMR existe, on lui délègue la tâche (même si on // sait qu'il va peut-être nous la réassigner) - pVMR->DrawOsdText(*this, true); + pVMR->DrawOsdText(*this, true, bLast); else DoInvalidate(); } } /// Écriture d'un nouveau texte dans ce rectangle OSD +/// \param[in] bLast \p true si cet affichage est le dernier d'un groupe d'affichages simultanés /// \param[in] pszFmt Chaîne format style \p printf /// \param[in] ... Liste d'arguments selon format -void COsdObject::SetText(LPCTSTR pszFmt, ...) +void COsdObject::SetText(bool bLast, LPCTSTR pszFmt, ...) { Clear(); // Effacement de l'éventuel texte précédent @@ -285,9 +288,11 @@ nTextSize = _vsntprintf_s(szText, _countof(szText)-1, pszFmt, argptr); szText[nTextSize] = 0; va_end(argptr); - Draw(); - cOSD.last_event = GetTickCount(); - cOSD.ProcessTimeEvent(); + Draw(bLast); + if (bLast) { + cOSD.last_event = GetTickCount(); + cOSD.ProcessTimeEvent(); + } } /// Obtenir les références du texte à afficher @@ -365,22 +370,11 @@ // de fort zoom) LONG nFHgt = max(32, LONG(sqrt(fDim))/24); - // ... mais néanmoins, la hauteur ne saurait être inféZZZZZZdrieure au tiers de l'affichage + // ... mais néanmoins, la hauteur ne saurait être inférieure au tiers de l'affichage // (cas possible si la vidéo est forcée en largeur et que la fenêtre est très aplatie) return min(nHgt/3, nFHgt); } -/// Affichage du nom de la chaîne et du nom de l'émission en cours -/// param[in] canal Descripteur de la chaîne courante -/// \todo Vérifier que l'émission en cours est bien disponible (au démarrage, il arrive -/// que l'émission suivante soit chargée en premier et soit temporairement seule disponible) -void COsdAllObjects::DisplayChannelInfo(const Chaine & canal) -{ - cTopRight.SetText(TEXT("%") A2t, canal.nom); - if (canal.emi_count > 0) - cTopRight2.SetText(TEXT("%s"), canal.emis[0].nom); -} - /// Effacement de tous les objets OSD affichés void COsdAllObjects::Clear() { @@ -440,19 +434,19 @@ /// Masquer tous les objets définis void COsdAllObjects::Hide() { - cTopRight.Hide(); - cTopRight2.Hide(); - cBotRight.Hide(); - cBotLeft.Hide(); + cTopRight.Hide(false); + cTopRight2.Hide(false); + cBotRight.Hide(false); + cBotLeft.Hide(true); } /// Redessiner tous les objets définis void COsdAllObjects::Redraw() { - cTopRight.Draw(); - cTopRight2.Draw(); - cBotRight.Draw(); - cBotLeft.Draw(); + cTopRight.Draw(false); + cTopRight2.Draw(false); + cBotRight.Draw(false); + cBotLeft.Draw(true); } /// Actualisation des rectangles et de la police d'affichage @@ -571,7 +565,7 @@ return ar; } -void CVideoMixingRenderer::DrawOsdText(COsdObject & cOsdObj, bool bHidden) +void CVideoMixingRenderer::DrawOsdText(COsdObject & cOsdObj, bool bHidden, bool bLast) { // Par défaut, on ne dessine pas d'objet. En lieu et place, on demande à l'objet appelant // d'invalider son rectangle, de façon à ce que le prochain appel à WM_PAINT provoque @@ -602,6 +596,7 @@ // Calcule le rectangle de la vidéo : RECT sRect = PlaceVideoInRect(CalcCliRect()); + // myprintf(TEXT("SetVideoPosition([") RECTFMT(",") TEXT("])\n"), RECTPARM(sRect)); SetVideoPosition(&sRect, video_pan_mode==pm_Stretch); } @@ -803,7 +798,8 @@ /// Affichage d'un texte OSD /// \param[in] cOsdObj Référence sur l'objet à afficher /// \param[in] bHidden Texte invisible si \p true (ne dessiner que le fond) - virtual void DrawOsdText(COsdObject & cOsdObj, bool bHidden); + /// \param[in] bLast \p true si cet affichage est le dernier d'un groupe d'affichages simultanés + virtual void DrawOsdText(COsdObject & cOsdObj, bool bHidden, bool bLast); /// Effacement de tout le contenu OSD couramment affiché virtual void ClearOsd(); @@ -913,7 +909,7 @@ if (FAILED(hr)) return erreur(TEXT("Nombre de modes de désentrelacement non trouvé"), hr); - myprintf(TEXT("num : %i\n"), num); + myprintf(TEXT("Nombre de modes de désentrelacement : %i\n"), num); GUID guid[1]; num = 1; @@ -1209,6 +1205,10 @@ /// Définition de la position d'affichage et du ratio d'aspect. /// \param[in] pDstRect Rectangle de la nouvelle position de l'affichage /// \param[in] bEtirer Déformer la vidéo si nécessaire pour remplir le rectangle +/// \todo En VMR9 seulement, si on positionne la fenêtre hors de l'écran par en haut et/ou par +/// à gauche, la vidéo refuse de sortir de l'écran par ces côtés-là, se décalant en conséquence +/// par rapport au rectangle d'affichage. Ce n'est que modérément gênant, mais on pourrait +/// quand même y chercher une solution éventuellement. HRESULT CVideoMixingRenderer9::SetVideoPosition(const LPRECT pDstRect, bool bEtirer) const { HRESULT hr = E_FAIL; @@ -1370,7 +1370,7 @@ TEXT("To correct this problem, try changing your display to use ") \ TEXT("16-bit or 32-bit color depth in the Display Control Panel applet.") -void CVideoMixingRenderer9::DrawOsdText(COsdObject & cOsdObj, bool bHidden) +void CVideoMixingRenderer9::DrawOsdText(COsdObject & cOsdObj, bool bHidden, bool bLast) { OsdRefs sRefs; @@ -1382,7 +1382,7 @@ // Écriture du texte dans le bitmap TextOutInRect(hdcBmp, sRefs, bHidden); - if (!bHidden) { + if (!bHidden && bLast) { // Configuration de la structure du bitmap du VMR VMR9AlphaBitmap bmpInfo = { VMR9AlphaBitmap_hDC | VMR9AlphaBitmap_SrcColorKey, // dwFlags @@ -1406,10 +1406,10 @@ // Give the bitmap to the VMR for display HRESULT hr = pBMP->SetAlphaBitmap(&bmpInfo); - SelectObject(hdcBmp, hbmOld); - myprintf(TEXT("%?SetAlphaBitmap FAILED! hr=0x%x\r\n\r\n%s\n"), FAILED(hr), hr, STR_VMR_DISPLAY_WARNING); } + + SelectObject(hdcBmp, hbmOld); } void CVideoMixingRenderer9::ClearOsd() Modifié: trunk/rendering.h =================================================================== --- trunk/rendering.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/rendering.h 2009-01-30 21:00:14 UTC (rev 170) @@ -127,7 +127,8 @@ /// Affichage d'un texte OSD /// \param[in] cOsdObj Référence sur l'objet à afficher /// \param[in] bHidden Effacer le rectangle au lieu d'afficher le texte - virtual void DrawOsdText(COsdObject & cOsdObj, bool bHidden); + /// \param[in] bLast \p true si cet affichage est le dernier d'un groupe d'affichages simultanés + virtual void DrawOsdText(COsdObject & cOsdObj, bool bHidden, bool bLast); /// Invalidation du rectangle d'un objet OSD, afin de provoquer son réaffichage /// (appel délégué depuis \p COsdObject) @@ -215,17 +216,20 @@ void Invalidate(); /// Écriture d'un nouveau texte dans ce rectangle OSD + /// \param[in] bLast \p true si cet affichage est le dernier d'un groupe d'affichages simultanés /// \param[in] pszFmt Chaîne format style \p printf /// \param[in] ... Liste d'arguments selon format - void SetText(LPCTSTR pszFmt, ...); + void SetText(bool bLast, LPCTSTR pszFmt, ...); /// Provoquer l'affichage du contenu du rectangle. Cette fonction est appelée /// par \p SetText, mais peut aussi être utilisée pour rafraîchir un affichage /// déjà établi. - void Draw(); + /// \param[in] bLast \p true si cet affichage est le dernier d'un groupe d'affichages simultanés + void Draw(bool bLast); - /// Effacement (temporaire) d'un texte existant dans le rectanble OSD. - void Hide(); + /// Effacement (temporaire) d'un texte existant dans le rectangle OSD. + /// \param[in] bLast \p true si cet effacement est le dernier d'un groupe d'effacements simultanés + void Hide(bool bLast); /// Point d'appel pour redessiner cet objet OSD en réponse à \p WM_PAINT /// \param[in] hDC "Device context" à utiliser @@ -392,27 +396,30 @@ /// Affichage du nom de la chaîne et du nom de l'émission en cours /// \param[in] canal Descripteur de la chaîne courante - void DisplayChannelInfo(const Chaine & canal); + void DisplayChannelInfo(const Chaine & canal) { + cTopRight.SetText(false, TEXT("%") A2t, canal.nom); + cTopRight2.SetText(true, TEXT("%s"), canal.getCurrentProgramName(TEXT("...")));} /// Affichage d'un numéro de chaîne (affichage en cours de saisie) /// \param[in] nChanNumber Numéro à afficher void DisplayChannelNumber(WORD nChanNumber) { - cTopRight.SetText(TEXT("%i"), nChanNumber);} + cTopRight.SetText(true, TEXT("%i"), nChanNumber);} /// Affichage du volume sonore /// \param[in] nCurrentVolume niveau de volume courant void DisplayVolume(long nCurrentVolume) { - cBotLeft.SetText(TEXT("Volume %i"), nCurrentVolume);} + cBotLeft.SetText(true, TEXT("Volume %i"), nCurrentVolume);} /// Affichage du zoom /// \param[in] nZoomRatio zoom courant void DisplayZoom(int nZoomRatio) { - cBotLeft.SetText(TEXT("Zoom %i%%"), nZoomRatio);} + cBotLeft.SetText(true, TEXT("Zoom %i%%"), nZoomRatio);} /// Affichage de l'état "mute" /// \param[in] bMuted true si on est en mode silencieux void DisplayMute(bool bMuted) { - cBotRight.SetText(bMuted ? TEXT("Sourdine") : TEXT(" "));} // si false, un espace pour effacer + cBotRight.SetText(true, + bMuted ? TEXT("Sourdine") : TEXT(" "));} // si false, un espace pour effacer /// Effacement de tous les objets OSD affichés void Clear(); Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/res.rc 2009-01-30 21:00:14 UTC (rev 170) @@ -260,8 +260,8 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN CONTROL "",IDC_LIST_EPG,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,0,0,569,282 - COMBOBOX IDC_METHOD_EPG,7,290,54,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_AUDIO_EPG,69,290,54,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_METHOD,7,290,54,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_AUDIO,69,290,54,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Enregistrer",IDC_RECORD,131,289,54,14 PUSHBUTTON "Mettre à jour",IDC_UPDATE,446,289,54,14 DEFPUSHBUTTON "Fermer",IDOK,508,289,54,14 @@ -597,12 +597,11 @@ IDD_EPG DLGINIT BEGIN - IDC_METHOD_EPG, 0x403, 2, 0 + IDC_METHOD, 0x403, 2, 0 0x0061, 0 END - ///////////////////////////////////////////////////////////////////////////// // // RCDATA Modifié: trunk/resource.h =================================================================== --- trunk/resource.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/resource.h 2009-01-30 21:00:14 UTC (rev 170) @@ -77,8 +77,6 @@ #define IDC_VERIF_FREQ_START 1051 #define IDC_METHOD 1052 #define IDC_AUDIO 1053 -#define IDC_AUDIO_EPG 1057 -#define IDC_METHOD_EPG 1058 #define IDC_POUCHINTVMOD_URL 1059 #define IDC_PASWD 1060 #define IDC_AFTER 1061 Modifié: trunk/search.cpp =================================================================== --- trunk/search.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/search.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -124,10 +124,16 @@ return E_FAIL; // Aucun filtre trouvé } -// 1er pin non connecté +/** + * Recherche de la première broche d'un filtre, pour une direction donnée. + * \param[in] pFilter Interface du filtre dans lequel la recherche s'effectue + * \param[in] dir Direction de la broche recherchée (entrée ou sortie) + * \param[out] result Interface de la broche trouvée + * \retval \p S_OK en cas de succès + **/ HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, CComPtr & result) { - myprintf(TEXT("** cherche_pin\n")); + // myprintf(TEXT("** cherche_pin\n")); CComPtr pEnumPins; HRESULT hr = pFilter->EnumPins(&pEnumPins); Modifié: trunk/search.h =================================================================== --- trunk/search.h 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/search.h 2009-01-30 21:00:14 UTC (rev 170) @@ -28,12 +28,12 @@ #pragma once /** - * Recherche de la première broche non connectée d'un filtre, pour une direction donnée. - * \param[in] pFilter Interfac du filtre dans lequel la recherche s'effectue + * Recherche de la première broche d'un filtre, pour une direction donnée. + * \param[in] pFilter Interface du filtre dans lequel la recherche s'effectue * \param[in] dir Direction de la broche recherchée (entrée ou sortie) * \param[out] result Interface de la broche trouvée - * \retval S_OK en cas de succès -*/ + * \retval \p S_OK en cas de succès + **/ HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, CComPtr & result); /** @@ -264,7 +264,7 @@ pFilter(pFltr) { myprintf( - TEXT("CSearchByCategory_Get: clsid=") GUIDFMT TEXT(", nom=%s\n"), + TEXT("CSearchByCategory_Get: clsid=") GUIDFMT TEXT(",\n\tnom=%s\n"), GUIDPARM(clsid), pszSrch); pFltr.Release(); // précaution Modifié: trunk/trayicon.cpp =================================================================== --- trunk/trayicon.cpp 2009-01-22 15:08:46 UTC (rev 169) +++ trunk/trayicon.cpp 2009-01-30 21:00:14 UTC (rev 170) @@ -57,8 +57,14 @@ if (ixChaine_ok(ixChaineCourante)) { const Chaine & canal_courant = Canaux[ixChaineCourante]; - _stprintf_s(szTip, _countof(szTip), - TEXT("%") A2t TEXT(" - %s"), canal_courant.nom, canal_courant.emis[0].nom); + strcpy_T(szTip, canal_courant.nom); + + LPCTSTR pszProgramName = canal_courant.getCurrentProgramName(NULL); + + if (pszProgramName) { + strcat_T(szTip, TEXT(" - ")); + strcat_T(szTip, pszProgramName); + } uFlags |= NIF_TIP; } } From pouchintv-dev at baysse.fr Sat Jan 31 17:23:33 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sat, 31 Jan 2009 17:23:33 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r171 - in trunk: . BaseClasses lzma/LzmaUtil tinyxml tools/ConditionalHeaderGenerator tools/GeneRealVersion Message-ID: <20090131162333.6B3965F8CA@mail.baysse.fr> Author: gingko Date: 2009-01-31 17:23:32 +0100 (sam, 31 jan 2009) New Revision: 171 Added: trunk/BaseClasses/baseclasses_2005.sln trunk/BaseClasses/baseclasses_2005.vcproj trunk/Pouchin TV_2005.sln trunk/Pouchin TV_2005.vcproj trunk/lzma/LzmaUtil/LzmaUtil_2005.sln trunk/lzma/LzmaUtil/LzmaUtil_2005.vcproj trunk/tinyxml/tinyXmlTestSTL_2005.vcproj trunk/tinyxml/tinyXmlTest_2005.vcproj trunk/tinyxml/tinyxmlSTL_2005.vcproj trunk/tinyxml/tinyxml_2005.sln trunk/tinyxml/tinyxml_lib_2005.vcproj trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator_2005.sln trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator_2005.vcproj trunk/tools/GeneRealVersion/GeneRealVersion_2005.sln trunk/tools/GeneRealVersion/GeneRealVersion_2005.vcproj Modified: trunk/BaseClasses/baseclasses.sln trunk/BaseClasses/baseclasses.vcproj trunk/Pouchin TV.sln trunk/Pouchin TV.vcproj trunk/atlbase_ptvm.h trunk/lzma/LzmaUtil/LzmaUtil.sln trunk/lzma/LzmaUtil/LzmaUtil.vcproj trunk/tinyxml/tinyXmlTest.vcproj trunk/tinyxml/tinyXmlTestSTL.vcproj trunk/tinyxml/tinyxml.sln trunk/tinyxml/tinyxmlSTL.vcproj trunk/tinyxml/tinyxml_lib.vcproj trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.sln trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.vcproj trunk/tools/GeneRealVersion/GeneRealVersion.sln trunk/tools/GeneRealVersion/GeneRealVersion.vcproj Log: Migration vers Visual Studio 2008 : Les fichiers de projets et de solutions "*.vcproj" et "*.sln" sont mis à jour vers le format utilisé par Visual Studio 2008 (ou Visual C++ Express 2008). À l'usage des personnes qui utilisent toujours Visual Studio 2005, des versions spéciales de ces fichiers sont ajoutées pour qu'ils puissent continuer à utiliser cet environnement. Ces nouveaux fichiers ont les mêmes noms que les fichiers d'origine, avec les caractères "_2005" ajoutés à la fin du nom de base. Les utilisateurs de Visual Studio 2005 (ou de Visual C++ Express 2005) devront donc systématiquement rechercher ces noms de solutions et de projets se terminant par "_2005". Autre modification : altbase_ptvm.h : * Correction d'un petit bug empêchant la compilation de la r170 avec les éditions Visual C++ Express. Modifié: trunk/BaseClasses/baseclasses.sln =================================================================== --- trunk/BaseClasses/baseclasses.sln 2009-01-30 21:00:14 UTC (rev 170) +++ trunk/BaseClasses/baseclasses.sln 2009-01-31 16:23:32 UTC (rev 171) @@ -1,24 +1,36 @@ ? -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "BaseClasses.vcproj", "{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_MBCS|Win32 = Debug_MBCS|Win32 + Debug_MBCS|x64 = Debug_MBCS|x64 Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release_MBCS|Win32 = Release_MBCS|Win32 + Release_MBCS|x64 = Release_MBCS|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|Win32.ActiveCfg = Debug_MBCS|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|Win32.Build.0 = Debug_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|x64.ActiveCfg = Debug_MBCS|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|x64.Build.0 = Debug_MBCS|x64 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.ActiveCfg = Debug|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.Build.0 = Debug|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.ActiveCfg = Debug|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.Build.0 = Debug|x64 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|Win32.ActiveCfg = Release_MBCS|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|Win32.Build.0 = Release_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|x64.ActiveCfg = Release_MBCS|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|x64.Build.0 = Release_MBCS|x64 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.ActiveCfg = Release|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.Build.0 = Release|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.ActiveCfg = Release|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modifié: trunk/BaseClasses/baseclasses.vcproj =================================================================== --- trunk/BaseClasses/baseclasses.vcproj 2009-01-30 21:00:14 UTC (rev 170) +++ trunk/BaseClasses/baseclasses.vcproj 2009-01-31 16:23:32 UTC (rev 171) @@ -1,11 +1,12 @@ + + Ajouté: trunk/BaseClasses/baseclasses_2005.sln =================================================================== --- trunk/BaseClasses/baseclasses_2005.sln (rev 0) +++ trunk/BaseClasses/baseclasses_2005.sln 2009-01-31 16:23:32 UTC (rev 171) @@ -0,0 +1,38 @@ +? +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "BaseClasses_2005.vcproj", "{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_MBCS|Win32 = Debug_MBCS|Win32 + Debug_MBCS|x64 = Debug_MBCS|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release_MBCS|Win32 = Release_MBCS|Win32 + Release_MBCS|x64 = Release_MBCS|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|Win32.ActiveCfg = Debug_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|Win32.Build.0 = Debug_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|x64.ActiveCfg = Debug_MBCS|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug_MBCS|x64.Build.0 = Debug_MBCS|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.ActiveCfg = Debug|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|Win32.Build.0 = Debug|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.ActiveCfg = Debug|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Debug|x64.Build.0 = Debug|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|Win32.ActiveCfg = Release_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|Win32.Build.0 = Release_MBCS|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|x64.ActiveCfg = Release_MBCS|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release_MBCS|x64.Build.0 = Release_MBCS|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.ActiveCfg = Release|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|Win32.Build.0 = Release|Win32 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.ActiveCfg = Release|x64 + {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal Ajouté: trunk/BaseClasses/baseclasses_2005.vcproj =================================================================== --- trunk/BaseClasses/baseclasses_2005.vcproj (rev 0) +++ trunk/BaseClasses/baseclasses_2005.vcproj 2009-01-31 16:23:32 UTC (rev 171) @@ -0,0 +1,830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modifié: trunk/Pouchin TV.sln =================================================================== --- trunk/Pouchin TV.sln 2009-01-30 21:00:14 UTC (rev 170) +++ trunk/Pouchin TV.sln 2009-01-31 16:23:32 UTC (rev 171) @@ -1,5 +1,5 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pouchin TV", "Pouchin TV.vcproj", "{E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}" ProjectSection(ProjectDependencies) = postProject {C406DAEC-0886-4771-8DEA-9D7329B46CC1} = {C406DAEC-0886-4771-8DEA-9D7329B46CC1} Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2009-01-30 21:00:14 UTC (rev 170) +++ trunk/Pouchin TV.vcproj 2009-01-31 16:23:32 UTC (rev 171) @@ -1,11 +1,12 @@ - - - - - - - - - +