From pouchintv-dev at baysse.fr Wed Feb 18 08:30:29 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Wed, 18 Feb 2009 08:30:29 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r172 - in trunk: . BaseClasses tools tools/GeneRealVersion Message-ID: <20090218073029.951136EED2@mail.baysse.fr> Author: gingko Date: 2009-02-18 08:30:27 +0100 (mer, 18 fév 2009) New Revision: 172 Added: trunk/Lisez-moi (setup).txt trunk/Setup.vcproj trunk/Setup_2005.vcproj Modified: trunk/BaseClasses/Doxyfile trunk/BaseClasses/cprop.cpp trunk/BaseClasses/streams.h trunk/BaseClasses/winutil.cpp trunk/BaseClasses/wxutil.h trunk/Pouchin TV.sln trunk/Pouchin TV.vcproj trunk/Pouchin TV_2005.sln trunk/Pouchin TV_2005.vcproj trunk/Programme_Install.nsi trunk/atlbase_ptvm.h trunk/base.h trunk/capture.cpp trunk/channels.cpp trunk/channels.h trunk/epg.cpp trunk/epgfilter.cpp trunk/ini.cpp trunk/main.cpp trunk/recprog.cpp trunk/res.rc trunk/tools/GeneRealVersion.exe trunk/tools/GeneRealVersion/GeneRealVersion.vcproj trunk/tools/GeneRealVersion/GeneRealVersion_2005.vcproj trunk/tools/GeneRealVersion/main.c trunk/version.cmd Log: Identification des versions, Projet d'installation, améliorations mineures, bugs corrigés. recprog.cpp, channel.h, channel.cpp : * Le menu de sélection des chaînes, dans le dialogue des enregistrements programmés, inclut maintenant le numéro "TSID" de la chaîne devant le nom de celle-ci, afin de faire ressortir les chaînes appartenant au même multiplex. version.cmd, GeneRealVersion, Programme_Install.nsi et fichiers projets : * Réécriture du fichier "version.cmd", pour produire des tests plus avancés du numéro de version et de la version de Visual Studio utilisée (en gros, les fichiers d'en-tête sont générés systématiquement sous un nom temporaire, puis comparés avec leurs versions précédentes, et renommés si des différences sont trouvées, ceci gérant une mise à jour correcte des dates de modification de ces fichiers) * Ajout d'arguments à GeneRealVersion afin de rendre ce qui précède possible. * Ajout de projets "Setup.vcproj/Setup_2005.vcproj" pour faciliter la génération du fichier d'installation. * Toutes les configurations, y compris les versions "Release", génèrent maintenant le fichier "Pouchin TV Mod.pdb" : en effet, ceci peut être utile pour analyser les dumps "post-mortem" produits par certains plantages. En conséquence, il conviendrait de sauvegarder ce fichier (en x86 et x64) et le mettre à disposition des développeurs lors de la sortie des versions officielles futures. Programme_Install.nsi : * Ajout d'un test de présence du processus Pouchin TV Mod lors de la désinstallation. Le programme est quitté si c'est le cas. ini.cpp, res.rc : * Modification de l'effet du caractère "?" dans les motifs de noms d'enregistrements (maintenant, il supprime aussi les caractères qui le **précèdent** si le champ précédent est vide) * Modification du motif de noms d'enregistrements par défaut (qui était toujours incorrect par rapport aux versions antérieures de Pouchin TV Mod). main.cpp : * Inclusion d'informations supplémentaires dans le dialogue "À propos" pour mieux identifier la version compilée. capture.cpp : * Correctif visant à éviter qu'un flux TS corrompu puisse provoquer un plantage de l'application. epgfilter.cpp : * Correction d'un bug susceptible d'introduire des corruptions du contenu de la liste des chaînes. altbase_ptvm.h : * Quelques éléments modifiés base.h : * Ajout de quelques macros facilitant les patches à "qedit.h" dans le Windows SDK, pour pallier au fait que "dxtrans.h" n'est plus inclus dans le DirectX SDK depuis fin 2007. BaseClasses (4 fichiers) : * Mise à jour des fichiers modifiés par rapport au Windows SDK version 6.1 Modifié: trunk/BaseClasses/Doxyfile =================================================================== --- trunk/BaseClasses/Doxyfile 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/BaseClasses/Doxyfile 2009-02-18 07:30:27 UTC (rev 172) @@ -1222,6 +1222,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/BaseClasses/cprop.cpp =================================================================== --- trunk/BaseClasses/cprop.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/BaseClasses/cprop.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -149,7 +149,7 @@ // This pointer may be NULL when calculating size - pPropertyPage = (CBasePropertyPage *) GetWindowLongPtr(hwnd, DWLP_USER); + pPropertyPage = _GetWindowLongPtr(hwnd, DWLP_USER); if (pPropertyPage == NULL) { return (LRESULT) 1; } @@ -363,7 +363,8 @@ CBasePropertyPage *pPropertyPage; { - pPropertyPage = (CBasePropertyPage *) GetWindowLongPtr(hwnd, DWLP_USER); + pPropertyPage = _GetWindowLongPtr(hwnd, DWLP_USER); + if (pPropertyPage->m_hwnd == NULL) { return 0; } Modifié: trunk/BaseClasses/streams.h =================================================================== --- trunk/BaseClasses/streams.h 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/BaseClasses/streams.h 2009-02-18 07:30:27 UTC (rev 172) @@ -123,6 +123,27 @@ #ifndef DWLP_USER #define DWLP_USER DWLP_DLGPROC + sizeof(DLGPROC) #endif + + +#pragma warning(push) +#pragma warning(disable: 4312 4244) +// _GetWindowLongPtr +// Templated version of GetWindowLongPtr, to suppress spurious compiler warning. +template +T _GetWindowLongPtr(HWND hwnd, int nIndex) +{ + return (T)GetWindowLongPtr(hwnd, nIndex); +} + +// _SetWindowLongPtr +// Templated version of SetWindowLongPtr, to suppress spurious compiler warning. +template +LONG_PTR _SetWindowLongPtr(HWND hwnd, int nIndex, T p) +{ + return SetWindowLongPtr(hwnd, nIndex, (LONG_PTR)p); +} +#pragma warning(pop) + /////////////////////////////////////////////////////////////////////////// // End Platform SDK definitions /////////////////////////////////////////////////////////////////////////// @@ -171,5 +192,11 @@ #include // External device control interface defines #include // audio filter device error event codes + + +//#else +// #ifdef DEBUG +// #pragma message("STREAMS.H included TWICE") +// #endif #endif // __STREAMS__ Modifié: trunk/BaseClasses/winutil.cpp =================================================================== --- trunk/BaseClasses/winutil.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/BaseClasses/winutil.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -425,7 +425,8 @@ // structure. IF we get any messages before WM_NCCREATE we will // pass them to DefWindowProc. - CBaseWindow *pBaseWindow = (CBaseWindow *)GetWindowLongPtr(hwnd,0); + CBaseWindow *pBaseWindow = _GetWindowLongPtr(hwnd,0); + if (pBaseWindow == NULL) { // Get the structure pointer from the create struct. @@ -451,7 +452,10 @@ #ifdef DEBUG SetLastError(0); // because of the way SetWindowLong works #endif - LONG_PTR rc = SetWindowLongPtr(hwnd, (DWORD) 0, (LONG_PTR) pBaseWindow); + + LONG_PTR rc = _SetWindowLongPtr(hwnd, (DWORD) 0, pBaseWindow); + + #ifdef DEBUG if (0 == rc) { // SetWindowLong MIGHT have failed. (Read the docs which admit Modifié: trunk/BaseClasses/wxutil.h =================================================================== --- trunk/BaseClasses/wxutil.h 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/BaseClasses/wxutil.h 2009-02-18 07:30:27 UTC (rev 172) @@ -196,7 +196,13 @@ // accessor thread calls this when done with thread (having told thread // to exit) void Close() { + + // Disable warning: Conversion from LONG to PVOID of greater size +#pragma warning(push) +#pragma warning(disable: 4312) HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hThread, 0); +#pragma warning(pop) + if (hThread) { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); Ajouté: trunk/Lisez-moi (setup).txt =================================================================== --- trunk/Lisez-moi (setup).txt (rev 0) +++ trunk/Lisez-moi (setup).txt 2009-02-18 07:30:27 UTC (rev 172) @@ -0,0 +1,32 @@ +Pouchin TV Mod, projet "Setup". + +Ce projet permet de générer le fichier d'installation de Pouchin TV Mod. + +Il ne fonctionne actuellement **pas** avec les versions Express de Visual Studio +(car celles-ci ne peuvent pas compiler en mode 64 bits) ; ceci sera peut-être +résolu dans une version ultérieure. + +Étant donné que ce fichier va contenir à la fois la version 32 bits et la version 64 +bits de Pouchin TV Mod, aucune dépendance n'est définie par rapport aux autres projets +de cette solution. +L'utilisateur est responsable d'avoir préalablement correctement compilé les deux +versions, 32 bits et 64 bits, dans leur configuration "Release" (ce sont ces deux +versions qui sont incluses dans le fichier d'installation). + +La génération du fichier d'installation est basée sur le logiciel NSIS +(Nullsoft Scriptable Install System). +Ce logiciel doit, bien évidemment, avoir été préalablement installé sur votre +ordinateur pour que cette génération puisse fonctionner. +L'installation doit être réalisée dans le dossier "%ProgramFiles%\NSIS\" (ainsi qu'il +est proposé par défaut), autrement il faudra modifier le projet en conséquence pour +que cela fonctionne correctement. + +Vous pouvez le télécharger gratuitement à l'adresse suivante : +http://nsis.sourceforge.net/ + +Toutes ces conditions étant satisfaites, vous devriez pouvoir produire un fichier +d'installation, simplement en sélectionnant la commande "Générer", appliquée +sur le projet "Setup". + +Le fichier résultant, "PouchinTVMod_setup.exe" sera alors produit dans le +répertoire général de la solution. Modifié: trunk/Pouchin TV.sln =================================================================== --- trunk/Pouchin TV.sln 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/Pouchin TV.sln 2009-02-18 07:30:27 UTC (rev 172) @@ -10,6 +10,11 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tinyxml", "tinyxml\tinyxml_lib.vcproj", "{C406DAEC-0886-4771-8DEA-9D7329B46CC1}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Setup", "Setup.vcproj", "{0A1A8A49-A616-442F-A2A9-007ED24AB66A}" + ProjectSection(ProjectDependencies) = postProject + {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B} = {E40974CC-65ED-4E0D-A2E2-3885C2C8A25B} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_SBCS|Win32 = Debug_SBCS|Win32 @@ -70,6 +75,14 @@ {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 + {0A1A8A49-A616-442F-A2A9-007ED24AB66A}.Debug_SBCS|Win32.ActiveCfg = Release|Win32 + {0A1A8A49-A616-442F-A2A9-007ED24AB66A}.Debug_SBCS|x64.ActiveCfg = Release|Win32 + {0A1A8A49-A616-442F-A2A9-007ED24AB66A}.Debug|Win32.ActiveCfg = Release|Win32 + {0A1A8A49-A616-442F-A2A9-007ED24AB66A}.Debug|x64.ActiveCfg = Release|Win32 + {0A1A8A49-A616-442F-A2A9-007ED24AB66A}.Release_SBCS|Win32.ActiveCfg = Release|Win32 + {0A1A8A49-A616-442F-A2A9-007ED24AB66A}.Release_SBCS|x64.ActiveCfg = Release|Win32 + {0A1A8A49-A616-442F-A2A9-007ED24AB66A}.Release|Win32.ActiveCfg = Release|Win32 + {0A1A8A49-A616-442F-A2A9-007ED24AB66A}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/Pouchin TV.vcproj 2009-02-18 07:30:27 UTC (rev 172) @@ -28,6 +28,7 @@ > - + # # This file is part of Pouchin TV Mod, a free DVB-T viewer. @@ -30,11 +30,12 @@ ;Pour la gestion des sections !include "Sections.nsh" + ; Récupération du numéro de version (généré automatiquement au préalable) + !include "version.nsh" ;-------------------------------- ;Quelques constantes !define PRODUCT_NAME "Pouchin TV Mod" - !define PRODUCT_VERSION "0.4.0.0" !define PRODUCT_COMMENT "http://pouchintv.baysse.fr/, http://www.etud.insa-toulouse.fr/~mvelten/pouchintvmod/, http://pouchinteve.free.fr/" !define PRODUCT_INSTALL_DESCRIPTION "Installeur pour Pouchin TV Mod" !define PRODUCT_WEB_SITE "http://pouchintv.baysse.fr/" @@ -138,7 +139,7 @@ ;Crée le programme de suppression WriteUninstaller "$INSTDIR\Désinstaller.exe" - ;Ajout des la désinstallation + ;Ajout de la désinstallation WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$\"$INSTDIR\Désinstaller.exe$\"" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "InstallLocation" "$INSTDIR" @@ -168,7 +169,7 @@ ;Les répertoires sont "All Users" SetShellVarContext all - File "x64\Release\PouchinTVMod_x64.exe" + File "Release_x64\PouchinTVMod_x64.exe" File "AUTHORS" File "gpl.txt" File "canaux.ini" @@ -357,9 +358,33 @@ ;-------------------------------- ; Section Suppression +; TODO : Faire en sorte que ne soient retirés que les fichiers qui ont effectivement été installés. +; Voir exemple de comment faire ici : +; http://nsis.sourceforge.net/Uninstall_only_installed_files +; +; Lire aussi le "warning" dans la documentation "RMDir" de NSIS, expliquant pourquoi il est +; peu souhaitable d'exécuter une commande "RMDir /r" sur le répertoire d'installation de l'application. + Section "uninstall" SetShellVarContext all + ;Recherche si Pouchin TV Mod est lancé + FindWindow $0 "Pouchin TV Mod" + +${If} $0 != "0" + ;Envoie le message d'arrêt + SendMessage $0 ${WM_CLOSE} 0 0 $0 /TIMEOUT=10000 + + ;Recherche pour voir si il est quitté + FindWindow $0 "Pouchin TV Mod" + StrCmp $0 "0" suite + + MessageBox MB_ICONSTOP "Je ne peux continuer la désinstallation tant que $\"${PRODUCT_NAME}$\" ne sera pas arrêté." + Abort + +${EndIf} +suite: + ;Menu Démarrer !insertmacro MUI_STARTMENU_GETFOLDER Application $STARTMENU_FOLDER RMDir /r "$SMPROGRAMS\$STARTMENU_FOLDER" Ajouté: trunk/Setup.vcproj =================================================================== --- trunk/Setup.vcproj (rev 0) +++ trunk/Setup.vcproj 2009-02-18 07:30:27 UTC (rev 172) @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Ajouté: trunk/Setup_2005.vcproj =================================================================== --- trunk/Setup_2005.vcproj (rev 0) +++ trunk/Setup_2005.vcproj 2009-02-18 07:30:27 UTC (rev 172) @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Modifié: trunk/atlbase_ptvm.h =================================================================== --- trunk/atlbase_ptvm.h 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/atlbase_ptvm.h 2009-02-18 07:30:27 UTC (rev 172) @@ -76,8 +76,10 @@ IU* pt = p; p = NULL; return pt; } IU* operator = (IU* q) { Release(); p=q; p->AddRef(); return p;} - CComPtr & operator = (const CComPtr & r) { + IU* operator = (const CComPtr & r) { Release(); p=r.p; p->AddRef(); return *this;} + template IU* operator=(const CComPtr & r) { + Release(); p=dynamic_cast(r.p); p->AddRef(); return *this;} template HRESULT QueryInterface(QI** pp) const { return p->QueryInterface(__uuidof(QI), (void**)pp);} HRESULT CoCreateInstance(const GUID & g, IUnknown* u=NULL, unsigned long c=CLSCTX_ALL) { @@ -99,6 +101,8 @@ public: CComVariant() {VariantInit(this);} + CComVariant(long val) { + vt = VT_I4; lVal = val;} ~CComVariant() {VariantClear(this);} }; Modifié: trunk/base.h =================================================================== --- trunk/base.h 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/base.h 2009-02-18 07:30:27 UTC (rev 172) @@ -54,6 +54,23 @@ #include #include +// ********************************************************************************** +// * Les lignes qui suivent sont une mise en oeuvre d'une suggestion proposée dans * +// * un forum Microsoft pour pallier au fait que le fichier "dxtrans.h" n'est plus * +// * inclus dans le DirectX SDK au-delà de celui d'août 2007. * +// * * +// * Pour que cela fonctionne, il faut aussi ouvrir le fichier "qedit.h" (dans le * +// * Windows SDK !!) et y mettre en commentaires la ligne "#include "dxtrans.h" * +// * (ligne 498, en principe, mais ça peut changer selon les versions). * +// * Voir (Ctrl-clic pour suivre le lien dans Visual Studio) : ************************************************************** +// * http://social.msdn.microsoft.com/Forums/en-US/windowssdk/thread/ed097d2c-3d68-4f48-8448-277eaaf68252/#70fb4aca-960c-4a76-b48c-6b3fa328b271 * +// *********************************************************************************************************************************************** +#define __IDxtCompositor_INTERFACE_DEFINED__ +#define __IDxtAlphaSetter_INTERFACE_DEFINED__ +#define __IDxtJpeg_INTERFACE_DEFINED__ +#define __IDxtKey_INTERFACE_DEFINED__ +// (fin de mise en oeuvre de suggestion) + #include #include Modifié: trunk/capture.cpp =================================================================== --- trunk/capture.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/capture.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -374,12 +374,10 @@ void PS_buffer::traite_paquet(const TS_packet & p) { const TS_unwrapper uw_th(p.hdr); - bool new_PES_starts_here = p.hdr.payload_unit_start_indicator(); - UINT8 new_ccounter = p.hdr.continuity_counter(); - UINT8 diff_ccounter = (new_ccounter - continuity_counter) & 0x0f; + bool new_PES_starts_here = p.hdr.payload_unit_start_indicator(); + UINT8 new_ccounter = p.hdr.continuity_counter(); + UINT8 diff_ccounter = (new_ccounter - continuity_counter) & 0x0f; - continuity_counter = new_ccounter; - // Vérification de la continuité : if (diff_ccounter == 0) { myprintf(TEXT("paquet dupliqué dans %") A2t TEXT("\n"), nom_debug); @@ -405,12 +403,18 @@ } if (valid && uw_th.p_payload) { + INT32 ptr_size = INT32(&p.bytes[TS_SIZE]-uw_th.p_payload); + + if (ptr_size < 0) // si négatif, alors le paquet doit être corrompu ; en conséquence + return; // on l'ignore, et le test de continuité sera faux au prochain passage. + // Paquet valide et "Payload" présent - UINT32 ptr_size = UINT32(&p.bytes[TS_SIZE]-uw_th.p_payload); - pcGrab->byte_count += ptr_size; put_data(uw_th.p_payload, ptr_size, new_PES_starts_here); } + + // Mémoriser maintenant le compteur de continuité + continuity_counter = new_ccounter; } void PS_buffer::send() Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/channels.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -51,12 +51,16 @@ // Concaténation chemin et chaîne _stprintf_s(fileName, _countof(fileName), TEXT("%s.bmp"), nom); - _stprintf_s(pathName, _countof(pathName), TEXT("%s\\Icones\\"), dir); + _stprintf_s(pathName, _countof(pathName), TEXT("%sIcones\\"), dir); + myprintf(TEXT("FindFileRecur(\n\t\"%s\",\n\t\"%s\",\n\t"), pathName, fileName); if (FindFileRecur(pathName, fileName, &szChemin)) { + myprintf(TEXT("\"%s\")\n"),szChemin); hImage = (HBITMAP)LoadImage(NULL, szChemin, IMAGE_BITMAP, TAILLE_IMAGE_CHAINE, TAILLE_IMAGE_CHAINE, LR_LOADFROMFILE | LR_LOADTRANSPARENT); } + else + myprintf(TEXT("[échec])\n"),szChemin); free(szChemin); return hImage; @@ -161,12 +165,6 @@ return hImage; } -// Génération du nom affichable pour le menu -int Chaine::toMenuString(LPTSTR pstr, size_t bufSize) const -{ - return _stprintf_s(pstr, bufSize, TEXT("%4i : %") A2t, numeroChaine, nom); -} - /** * 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 @@ -363,20 +361,20 @@ void change_frequence(ULONG freq) { if (pBDAControl && pBDAFreq) { - HRESULT hr = pBDAControl->StartChanges(); - myprintf(TEXT("%?change_frequence pBDAControl->StartChanges(), hr=0x%08x\n"), FAILED(hr), hr); + HRESULT hr = pBDAControl->StartChanges(); + myprintf(TEXT("%?change_frequence pBDAControl->StartChanges(), hr=0x%08x\n"), FAILED(hr), hr); - hr = pBDAFreq->put_Bandwidth(8); - myprintf(TEXT("%?change_frequence pBDAFreq->put_Bandwidth(8), hr=0x%08x\n"), FAILED(hr), hr); + hr = pBDAFreq->put_Bandwidth(8); + myprintf(TEXT("%?change_frequence pBDAFreq->put_Bandwidth(8), hr=0x%08x\n"), FAILED(hr), hr); - hr = pBDAFreq->put_Frequency(freq); - myprintf(TEXT("%?change_frequence pBDAFreq->put_Frequency(%ul), hr=0x%08x\n"), FAILED(hr), freq, hr); + hr = pBDAFreq->put_Frequency(freq); + myprintf(TEXT("%?change_frequence pBDAFreq->put_Frequency(%ul), hr=0x%08x\n"), FAILED(hr), freq, hr); - hr = pBDAControl->CheckChanges(); - myprintf(TEXT("%?change_frequence pBDAControl->CheckChanges(), hr=0x%08xn"), FAILED(hr), hr); + hr = pBDAControl->CheckChanges(); + myprintf(TEXT("%?change_frequence pBDAControl->CheckChanges(), hr=0x%08xn"), FAILED(hr), hr); - hr = pBDAControl->CommitChanges(); - myprintf(TEXT("%?change_frequence pBDAControl->CommitChanges(), hr=0x%08x\n"), FAILED(hr), hr); + hr = pBDAControl->CommitChanges(); + myprintf(TEXT("%?change_frequence pBDAControl->CommitChanges(), hr=0x%08x\n"), FAILED(hr), hr); } } Modifié: trunk/channels.h =================================================================== --- trunk/channels.h 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/channels.h 2009-02-18 07:30:27 UTC (rev 172) @@ -53,7 +53,7 @@ /// 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("");} + return isOk() ? nom : TEXT("");} }; struct ChainePMT { @@ -63,7 +63,7 @@ liste_pistes sons; liste_pistes autr; - ChainePMT(); + ChainePMT(); char norme(void) const; bool operator == (const ChainePMT & cpmt) const; bool operator != (const ChainePMT & cpmt) const {return ! operator == (cpmt);}; @@ -133,8 +133,15 @@ (numeroChaine == canal2.numeroChaine && _stricmp(nom, canal2.nom) > 0); } /// Génération du nom affichable pour le menu - int toMenuString(LPTSTR pstr, size_t bufSize) const; + int toMenuString(LPTSTR pstr, size_t bufSize) const { + return _stprintf_s(pstr, bufSize, + TEXT("%4i : %") A2t, numeroChaine, nom, groupe); } + /// Génération du nom affichable pour le menu (avec TSID) + int toMenuString_tsid(LPTSTR pstr, size_t bufSize) const { + return _stprintf_s(pstr, bufSize, + TEXT("%4i [%u] : %") A2t, numeroChaine, TSID, nom); } + /** * 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 Modifié: trunk/epg.cpp =================================================================== --- trunk/epg.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/epg.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -171,8 +171,12 @@ /** * 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. + * \todo Améliorations à envisager : + * - Envisager sauvegarde de la dimension de cette boîte de dialogue, + * maintenant qu'elle est redimensionnable. + * - Griser les chaînes n'appartenant pas au même multiplex lorsque des + * enregistrements sont en cours. + * - Produire une mise à jour automatique (optionnelle ?) **/ INT_PTR CALLBACK EpgDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { Modifié: trunk/epgfilter.cpp =================================================================== --- trunk/epgfilter.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/epgfilter.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -24,10 +24,9 @@ * a modified version of this software. * See http://pouchintv.baysse.fr/ for updates. */ -#include "epgfilter.h" +#include "epgfilter.h" #include "base.h" - #include "main.h" #include "channels.h" #include "crc32.h" @@ -113,7 +112,7 @@ // chasser la plus ancienne, et décaler vers le bas selon le point d'insertion. if (cle < chaine.emis[0].cle) continue; // ça ne devrait pas arriver, mais si jamais l'émission juste reçue est la plus ancienne ... - for (i=0; i <= _countof(chaine.emis) && cle > chaine.emis[i+1].cle; ++i) + for (i=0; i < _countof(chaine.emis)-1 && cle > chaine.emis[i+1].cle; ++i) chaine.emis[i] = chaine.emis[i+1]; } else { // Nombre maximal d'émissions mémorisées non atteint : Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/ini.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -185,7 +185,7 @@ TCHAR scan_ini[]=TEXT("canaux.ini"); /// Motif par défaut pour nommer les enregistrements -static const TCHAR motif_noms_enreg_default[] = TEXT("%c? - %e %a-%m-%j %h-%M-%s"); +static const TCHAR motif_noms_enreg_default[] = TEXT("%e - ?%c %a-%m-%j %h-%M-%s"); /** * Chemin complet vers le fichier de configuration.\n @@ -433,87 +433,112 @@ // %h = heure // %M = minute // %s = secondes - int sav_pos = -1; // sauvegarde du début du groupe à ignorer si la prochaine zone est vide - int lmotif = (int)_tcslen(motif_noms_enreg); + int sav_pos = -1; // sauvegarde du début du groupe à ignorer si la prochaine zone est vide + // après un point d'interrogation + int lit_pos = -1; // sauvegarde du début du groupe à ignorer si la zone précédente était vide + // et qu'un point d'interrogation est ensuite rencontré + int lmotif = (int)_tcslen(motif_noms_enreg); for (int i=0; i=0 && temp==0) { - // Aucune donnée produite : on détruit les caractères littéraux précédents - // si un point d'interrogation les a précédés - nom[sav_pos] = 0; - sav_pos = -1; + if (temp==NULL) { // Aucune donnée produite + if (sav_pos>=0) { + // On détruit les caractères littéraux précédents + // si un point d'interrogation les a précédés + nom[sav_pos] = 0; + sav_pos = -1; + } + lit_pos = (int)_tcslen(nom); // mémoriser position pour effacement avant le '?' + } else + lit_pos = -1; + } else if (motif_noms_enreg[i] == L'?') { + // Le point d'interrogation indique que les caractères littéraux précédents sont ignorés + // si le champ "%" précédent n'insérait aucune donnée, et/ou que les caractères littéraux + // subséquents seront ignorés si le champ "%" suivant n'insère aucune donnée. + if (lit_pos>=0) { + // On détruit les caractères littéraux précédents + // si aucune donnée n'avait été insérée par le champ "%" précédent + nom[lit_pos] = 0; + lit_pos = -1; } - } else if (motif_noms_enreg[i] == L'?') { - // Le point d'interrogation indique que les caractères littéraux subséquents seront - // ignorés si le champ "%" suivant n'insère aucune donnée sav_pos = (int)_tcslen(nom); // -> on mémorise la position } else { temp = new TCHAR[2]; temp[0] = motif_noms_enreg[i]; temp[1] = L'\0'; } - if (temp != 0) { + if (temp != NULL) { _tcscat_s(nom, _countof(nom), temp); delete [] temp; } @@ -968,7 +993,6 @@ pNode->getStr(TEXT("Groupe"), canal.groupe, _countof(canal.groupe)); canal.khz = pNode->getInt(TEXT("Frequence")); - canal.ONID = (WORD)pNode->getInt(TEXT("ONID")); canal.TSID = (WORD)pNode->getInt(TEXT("TSID")); canal.SID = (WORD)pNode->getInt(TEXT("SID")); Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/main.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -934,16 +934,31 @@ if (resource.Extraction(IDR_AUTHORS)) { // Tout s'est bien passé: on peut utiliser la liste des contributeurs - SetDlgItemTextA(hwndDlg, IDC_AUTHORS, resource); + SetDlgItemTextA(hwndDlg, IDC_AUTHORS, (LPCSTR)resource); } // Ajoute la version dans la fenêtre { - char version[250]; - GetDlgItemTextA(hwndDlg, IDC_VERSION, version, _countof(version)); + TCHAR szVersion[96]; - sprintf_s(version, _countof(version), "%sversion %s", version, PTVM_VERSION_STR); - SetDlgItemTextA(hwndDlg, IDC_VERSION, version); + _stprintf_s(szVersion, + TEXT("%s ver. ") TEXT(PTVM_VERSION_STR) TEXT(" (") + #ifdef _WIN64 + TEXT("x64") + #else + TEXT("W32") + #endif + #ifdef _UNICODE + TEXT(" Unicode") + #else + TEXT(" SBCS") + #endif + #ifdef _DEBUG + TEXT(" Debug") + #endif + TEXT(")"), + szAppName); + SetDlgItemText(hwndDlg, IDC_VERSION, szVersion); } // Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/recprog.cpp 2009-02-18 07:30:27 UTC (rev 172) @@ -809,7 +809,7 @@ if (ixChaine_ok(ixChaine)) { TCHAR str[64]; - Canaux[ixChaine].toMenuString(str, _countof(str)); + Canaux[ixChaine].toMenuString_tsid(str, _countof(str)); SendMessage(hCtl, CB_SELECTSTRING, WPARAM(-1), LPARAM(str)); } } @@ -995,7 +995,7 @@ if (canal.etat != ec_inactive) { TCHAR wbuf[64]; - canal.toMenuString(wbuf, _countof(wbuf)); + canal.toMenuString_tsid(wbuf, _countof(wbuf)); LRESULT res = SendMessage(hCtl, CB_ADDSTRING, 0, (LPARAM)wbuf); if (res>=0) { Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/res.rc 2009-02-18 07:30:27 UTC (rev 172) @@ -197,7 +197,7 @@ BEGIN GROUPBOX "Noms des enregistrements",IDC_STATIC,7,7,276,67 EDITTEXT IDC_MOTIF_NOM_REC,14,18,262,12,ES_AUTOHSCROLL - LTEXT "%c = nom de la chaîne\t\t%n = numéro de chaîne (%N sur 2 chiffres)\n%e = nom de l'enregistrement\t? = texte suivant ignoré si champ suivant vide",IDC_STATIC,14,31,262,18 + LTEXT "%c = nom de la chaîne\t\t%n = numéro de chaîne (%N sur 2 chiffres)\n%e = nom de l'enregistrement\t? = ignorer texte adjacent à champ vide",IDC_STATIC,14,31,262,18 LTEXT "%a = année\t\t%m = mois\t\t%j = jour\n%h = heure\t\t%M = minute\t\t%s = secondes",IDC_STATIC,14,55,262,17 GROUPBOX "Enregistrements demandés depuis le guide",IDC_STATIC,7,77,276,40 EDITTEXT IDC_AVANCE_ENREG,14,93,36,14,ES_CENTER | ES_AUTOHSCROLL Modifié: trunk/tools/GeneRealVersion/GeneRealVersion.vcproj =================================================================== --- trunk/tools/GeneRealVersion/GeneRealVersion.vcproj 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/tools/GeneRealVersion/GeneRealVersion.vcproj 2009-02-18 07:30:27 UTC (rev 172) @@ -131,6 +131,7 @@ /> #include -#define TAB_SIZE (128) +#define TAB_SIZE 128 -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ char inBuff[TAB_SIZE] = {0}, buff[TAB_SIZE] = {0}, outBuff[TAB_SIZE] = {0}; + char ch; int i, j; int modifie = 0; FILE *fp; + if (argc<3) + return -1; // il faut deux arguments derrière l'appel + // Lit les caractères sur l'entrée standard fgets(inBuff, TAB_SIZE-1, stdin); // // Traite l'entrée - // Si on a l'entrée spaciale : nS pour non Svn, alors, on met un numéro de version se finissant pas .0.9999 + // Si on a l'entrée spéciale : nS pour non Svn, alors, on met un numéro de version se finissant pas .0.9999 if (inBuff[0] == 'n' && inBuff[1] == 'S') { // Pas versionné buff[0] = '0'; modifie = 9999; } else // Versionné. On récupère la révision - for (i=0; i 47) - buff[j++] = inBuff[i]; + else if (ch >= '0' && ch <= '9') + buff[j++] = ch; else - i=128; + i=TAB_SIZE; else - i=128; + i=TAB_SIZE; + } + } + } sprintf_s(outBuff, TAB_SIZE-1, "%s,%d", buff, modifie); // Lit la version majeure dans le fichier version - fopen_s(&fp, "version", "r"); - fgets(inBuff, TAB_SIZE-1, fp); - fclose(fp); + if (fopen_s(&fp, argv[2], "r")==0) { + fgets(inBuff, TAB_SIZE-1, fp); + fclose(fp); + } else + strcpy_s(inBuff, TAB_SIZE-1, "???"); memset(buff, 0, TAB_SIZE); - for (i=0, j=0; inBuff[i] != '\r' && inBuff[i] != '\n' && inBuff[1] != 0; i++) - buff[j++] = inBuff[i]; + for (i=0, j=0; (ch = inBuff[i]) != '\r' && ch != '\n' && ch != 0; i++) + buff[j++] = ch; // - // Génère la version en concaténant buff (contenant la version majeure lue), et outBuff (revision indiquée, ou déterminée) + // Génère la version en concaténant buff (contenant la version majeure lue), + // et outBuff (révision indiquée, ou déterminée) - fopen_s(&fp, "version.h", "wt"); sprintf_s(inBuff, TAB_SIZE-1, "%s,%s", buff, outBuff); - // - // Écrit les versions - sprintf_s(buff, TAB_SIZE-1, "#define PTVM_VERSION_RES %s\n", inBuff); - fputs(buff, fp); - // Remplace les ',' par des '.' par la version sous forme de chaînes de caractères - for (i=0; i=4 && argv[3] ? argv[3]:"", inBuff); + return 0; } Modifié: trunk/tools/GeneRealVersion.exe =================================================================== (les fichiers binaires diffèrent) Modifié: trunk/version.cmd =================================================================== --- trunk/version.cmd 2009-01-31 16:23:32 UTC (rev 171) +++ trunk/version.cmd 2009-02-18 07:30:27 UTC (rev 172) @@ -1,56 +1,74 @@ @echo off -rem Initialise la variable -set NO_SVN= +rem Nettoyage pr‚liminaire par pr‚caution : +if exist version_$temp$.txt del version_$temp$.txt -rem Si les deux fichiers de version existent, on ne r‚g‚nŠre pas -if exist "version.h" if exist "version.txt" goto finsvn - +echo #### rem Cherche si on est dans un repository -if not exist .svn\nul goto exporte +if exist .svn\nul ( + rem Extrait la version du SVN utilis‚e + svnversion -cn 2>NUL > version_$temp$.txt + if errorlevel 1 ( + echo #### L'utilitaire "svnversion", qui fait partie de "Subversion", n'est pas disponible. + echo #### Le num‚ro de version ne peut pas ˆtre g‚n‚r‚ correctement. + echo #### Pour disposer de cet utilitaire, veuillez t‚l‚charger et installer un package + echo #### binaire de "Subversion" l'adresse suivante : http://subversion.tigris.org/ + echo #### Suite cette installation, vous devrez alors avoir la commande "svnversion" + echo #### disponible dans le "PATH" en ligne de commande. + echo #### + if exist version_$temp$.txt del version_$temp$.txt + ) +) -rem Extrait la version du SVN utilis‚e -svnversion -cn 2>NUL > "version.txt_" -if errorlevel 1 ( - del "version.txt_" - goto svnmanquant +rem G‚n‚ration du num‚ro de version dans un fichier "version_$temp$.h", +rem ainsi que dans une variable d'environnement : +if exist version_$temp$.txt ( + type version_$temp$.txt | tools\GeneRealVersion.exe version_$temp$.h version "SET SVN_VERSION=" > set_version_$temp$.cmd + del version_$temp$.txt +) else ( + rem Version export‚e, tout est d‚j OK + echo nS | tools\GeneRealVersion.exe version_$temp$.h version "SET SVN_VERSION=" > set_version_$temp$.cmd ) -type "version.txt_" | tools\GeneRealVersion.exe > "version.txt" -del "version.txt_" -goto finsvn +call set_version_$temp$.cmd +del set_version_$temp$.cmd +echo %SVN_VERSION%> version.txt -:svnmanquant -echo. -echo Subversion n'est pas install‚. -echo Veuillez le t‚l‚charger l'adresse http://subversion.tigris.org/ puis relancer la compilation pour avoir la version complŠte. -echo. -set NO_SVN="1" +rem G‚n‚ration d'un fichier d'inclusion pour le num‚ro de version dans l'installeur +echo ; Ce fichier est généré automatiquement par 'version.cmd'> version.nsh +echo.>> version.nsh +echo !define PRODUCT_VERSION "%SVN_VERSION%">> version.nsh -rem Version export‚e, tout est d‚j OK -:exporte -rem if exist "version.txt" goto finsvn -echo nS | tools\GeneRealVersion.exe >NUL -rem "version.txt" -goto finsvn - -:finsvn -rem Affichage de la version compil‚e -echo. -echo Version compil‚e: -if "%NO_SVN%." == "." ( - type version.txt +rem Comparaison de "version_$temp$.h" avec le fichier "version.h" courant. +rem S'ils sont diff‚rents, "version_$temp$.h" devient le nouveau "version.h" +rem (ainsi la date de modification "version.h" ne change que si c'est appropri‚) +rem +echo n | comp version_$temp$.h version.h 2>NUL >NUL +rem Code retour : 0 = fichiers identiques, 1 = fichiers diff‚rents, 2 = fichier inexistant +if errorlevel 1 ( + if exist version.h del version.h + ren version_$temp$.h version.h + echo #### Un nouveau fichier de version "version.h" a ‚t‚ g‚n‚r‚ ) else ( - type version + del version_$temp$.h ) -echo. +rem Affichage de la version compil‚e +echo #### Version compil‚e: %SVN_VERSION% +echo #### + rem On recherche le type de compilateur : Express ou Studio -if exist "vstudio_edition.h" goto finvs +tools\ConditionalHeaderGenerator 3 > vstudio_edition_$TEMP$.h -rem Premier appel au compilateur => g‚n‚ration du header -echo. -echo PremiŠre compilation : cr‚ation du fichier "vstudio_edition.h" -echo. -tools\ConditionalHeaderGenerator 3 > vstudio_edition.h - -:finvs +rem Comparaison de "vstudio_edition_$TEMP$.h" avec le fichier "vstudio_edition.h" courant. +rem S'ils sont diff‚rents, "vstudio_edition_$TEMP$.h" devient le nouveau "vstudio_edition.h" +rem (ainsi la date de modification "vstudio_edition.h" ne change que si c'est appropri‚) +rem +echo n | comp vstudio_edition_$TEMP$.h vstudio_edition.h 2>NUL >NUL +rem Code retour : 0 = fichiers identiques, 1 = fichiers diff‚rents, 2 = fichier inexistant +if errorlevel 1 ( + if exist vstudio_edition.h del vstudio_edition.h + ren vstudio_edition_$TEMP$.h vstudio_edition.h + echo #### Un nouveau fichier "vstudio_edition.h" d'identification du compilateur a ‚t‚ g‚n‚r‚ +) else ( + del vstudio_edition_$TEMP$.h +) From pouchintv-dev at baysse.fr Sat Feb 21 23:44:55 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sat, 21 Feb 2009 23:44:55 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r173 - trunk Message-ID: <20090221224455.47D6C5F436@mail.baysse.fr> Author: gingko Date: 2009-02-21 23:44:54 +0100 (sam, 21 fév 2009) New Revision: 173 Modified: trunk/Pouchin TV_2005.vcproj trunk/base.cpp trunk/base.h trunk/channels.cpp trunk/graph.cpp trunk/graph.h trunk/ini.cpp trunk/ini.h trunk/main.cpp trunk/network.cpp trunk/recprog.cpp trunk/rendering.cpp trunk/rendering.h trunk/res.rc trunk/resource.h trunk/search.cpp trunk/search.h trunk/settings.cpp trunk/utils.h Log: Première version expérimentale implémentant le support du codec H264 (HD). channels.cpp, graph.h, graph.cpp, ini.h, ini.cpp, rendering.h, rendering.cpp, res.rc, settings.cpp : * Le graphe inclut maintenant un codec H264, s'insérant automatiquement lors de la sélection de chaînes HD. Ceci semble fonctionner à peu près bien, au moins avec les versions les plus récentes de ffdshow et CoreAVC. Je n'ai hélas pas encore réussi à trouver de codec fonctionnel pour le H264 en 64 bits, bien qu'il est probable que cela fonctionne si quelqu'un en déniche un. base.h, base.cpp : * Utilisation de l'objet "tstring" (qui est une déclinaison TCHAR des classes STL string ou wstring) pour gérer l'accumulation des messages d'erreur. graph.cpp : * Généralisation de la construction en aggrégats - maintenant statiques - des structures "AM_MEDIA_TYPE" et des structures pointées par celle-ci. graph.cpp, search.h, search.cpp : * Début d'implémentation - pas encore vraiment testée - de la possibilité, pour tous les codecs, des les spécifier comme "Aucun" (donc pas de codec disponible), ce qui veut dire bien sûr que la fonctionnalité correspondante ne sera pas assurée. graph.cpp, main.cpp : * La fonctionnalité de va-et-vient de fréquence au démarrage est remplacée par une resyntonisation automatique sur détection de l'événement "EC_PAUSED" dans le graphe (l'item de configuration correspondant n'est pas encore enlevé, mais n'est plus actif). util.h, search.cpp : * Création d'une macro "ENUM_ITF" pour faciliter les énumérations d'interfaces. settings.cpp : * Ajout d'un test manquant, détectant les modifications du motif de noms d'enregistrements, afin de provoquer l'activation du bouton "OK" pour valider cette modification. Modifié: trunk/Pouchin TV_2005.vcproj =================================================================== --- trunk/Pouchin TV_2005.vcproj 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/Pouchin TV_2005.vcproj 2009-02-21 22:44:54 UTC (rev 173) @@ -412,7 +412,7 @@ 0 && UINT(szBuffer[--nLen])<=' ') + szBuffer[nLen]=0; + + return tstring(szBuffer); +}; + +/** * Met en file d'attente le message d'erreur passé en paramètre pour un affichage ultérieur * - * \param[in] str Le message à stocker, et pouvant être passé à un printf - * ou si NULL, le message d'erreur sera récupéré automatiquement pour DirectShow - * \param[in] hr valeur de retour devant être testée (en cas d'erreur DShow), - * ou 0 si on doit l'ignorer. Ce sera la valeur retournée - * \param[in] ... variables optionnelles traitées par printf - * \return la valeur du hr passé en paramètre + * \param[in] str Le message à stocker, et pouvant être passé à un printf + * ou si NULL, le message d'erreur sera récupéré automatiquement pour DirectShow + * \param[in] hr valeur de retour devant être testée (en cas d'erreur DShow), + * ou 0 si on doit l'ignorer. Ce sera la valeur retournée + * \param[in] ... variables optionnelles traitées par printf + * \return la valeur du hr passé en paramètre **/ HRESULT erreur(LPCTSTR str, HRESULT hr, ...) { - // Buffer de stockage temporaire - TCHAR buffer[0x200]; - // Utile simplement si on passe un message d'erreur personnalisé if (str) { - LPTSTR pszNewErrBuf; + // Buffer de stockage temporaire + TCHAR buffer[0x200]; va_list argptr; va_start(argptr, hr); _vstprintf_s(buffer, str, argptr); va_end(argptr); - UINT nBufLen = UINT(_tcslen(buffer)+1); + if (!strErrBuf.empty()) + strErrBuf += TEXT("\n"); + strErrBuf += buffer; - if (pszErrBuf) { - static LPCTSTR pszEol = TEXT("\n"); - UINT nPrevLen = UINT(_tcslen(pszErrBuf)+_tcslen(pszEol)); - - nBufLen += nPrevLen; - pszNewErrBuf = new TCHAR[nBufLen]; - _tcscpy_s(pszNewErrBuf, nBufLen, pszErrBuf); - _tcscat_s(pszNewErrBuf, nBufLen, pszEol); - _tcscat_s(pszNewErrBuf, nBufLen, buffer); - delete [] pszErrBuf; - } else { - pszNewErrBuf = new TCHAR[nBufLen]; - _tcscpy_s(pszNewErrBuf, nBufLen, buffer); - } - pszErrBuf = pszNewErrBuf; - // Logue le message d'erreur myprintferror(buffer); } if (FAILED(hr) && hr!=lastRes) { - AMGetErrorText(hr, buffer, _countof(buffer)); - - erreur(TEXT("%s (code 0x%08x)"), S_OK, buffer, hr); + erreur(TEXT("%s (code 0x%08x)"), S_OK, GetErrorText(hr).c_str(), hr); lastRes = hr; } @@ -132,9 +137,9 @@ /** * Affiche les messages d'erreurs mis en file d'attente, ainsi que le nouveau message à la suite * - * \param[in] str le message à stocker, et à afficher en dernier - * \param[in] hr valeur de retour devant être testée (en cas d'erreur DShow), - * ou 0 si on doit l'ignorer. Ce sera la valeur retournée + * \param[in] str le message à stocker, et à afficher en dernier + * \param[in] hr valeur de retour devant être testée (en cas d'erreur DShow), + * ou 0 si on doit l'ignorer. Ce sera la valeur retournée **/ void affiche_erreurs(LPCTSTR str, HRESULT hr) { @@ -142,10 +147,9 @@ erreur(str, hr); // Affiche le(s) message(s) d'erreur(s), et vide la pile - if (pszErrBuf) { - MessageBox(hMainWnd, pszErrBuf, NULL, MB_ICONERROR); - delete [] pszErrBuf; - pszErrBuf = NULL; + if (!strErrBuf.empty()) { + MessageBox(hMainWnd, strErrBuf.c_str(), NULL, MB_ICONERROR); + strErrBuf.clear(); lastRes = S_OK; } } Modifié: trunk/base.h =================================================================== --- trunk/base.h 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/base.h 2009-02-21 22:44:54 UTC (rev 173) @@ -194,22 +194,31 @@ }; /** + * Obtenir, en clair, le message d'erreur correspondant à un code retour HRESULT. + * + * \param[in] hr Code retour à décoder + * \return Une chaîne de caractères, format \p tstring (= \p string ou \p wstring), + * contenant le message d'erreur correspondant + **/ +tstring GetErrorText(HRESULT hr); + +/** * Met en file d'attente le message d'erreur passé en paramètre pour un affichage ultérieur * - * \param[in] str Le message à stocker, et pouvant être passé à un printf - * ou si NULL, le message d'erreur sera récupéré automatiquement pour DirectShow - * \param[in] hr valeur de retour devant être testée (en cas d'erreur DShow), - * ou 0 si on doit l'ignorer. Ce sera la valeur retournée - * \param[in] ... variables optionnelles traitées par printf - * \return la valeur du hr passé en paramètre + * \param[in] str Le message à stocker, et pouvant être passé à un printf + * ou si NULL, le message d'erreur sera récupéré automatiquement pour DirectShow + * \param[in] hr valeur de retour devant être testée (en cas d'erreur DShow), + * ou 0 si on doit l'ignorer. Ce sera la valeur retournée + * \param[in] ... variables optionnelles traitées par printf + * \return la valeur du hr passé en paramètre **/ HRESULT erreur(LPCTSTR str, HRESULT hr, ...); /** * Affiche les messages d'erreurs mis en file d'attente, ainsi que le nouveau message à la suite * - * \param[in] str le message à stocker, et à afficher en dernier - * \param[in] hr valeur de retour devant être testée (en cas d'erreur DShow), - * ou 0 si on doit l'ignorer. Ce sera la valeur retournée + * \param[in] str le message à stocker, et à afficher en dernier + * \param[in] hr valeur de retour devant être testée (en cas d'erreur DShow), + * ou 0 si on doit l'ignorer. Ce sera la valeur retournée **/ void affiche_erreurs(LPCTSTR str, HRESULT hr=S_OK); Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/channels.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -53,14 +53,14 @@ _stprintf_s(fileName, _countof(fileName), TEXT("%s.bmp"), nom); _stprintf_s(pathName, _countof(pathName), TEXT("%sIcones\\"), dir); - myprintf(TEXT("FindFileRecur(\n\t\"%s\",\n\t\"%s\",\n\t"), pathName, fileName); + //myprintf(TEXT("FindFileRecur(\n\t\"%s\",\n\t\"%s\",\n\t"), pathName, fileName); if (FindFileRecur(pathName, fileName, &szChemin)) { - myprintf(TEXT("\"%s\")\n"),szChemin); + //myprintf(TEXT("\"%s\")\n"),szChemin); hImage = (HBITMAP)LoadImage(NULL, szChemin, IMAGE_BITMAP, TAILLE_IMAGE_CHAINE, TAILLE_IMAGE_CHAINE, LR_LOADFROMFILE | LR_LOADTRANSPARENT); } - else - myprintf(TEXT("[échec])\n"),szChemin); + //else + // myprintf(TEXT("[échec])\n"),szChemin); free(szChemin); return hImage; @@ -195,6 +195,9 @@ HRESULT Chaine::branche(bool reset_son) const { ULONG pid = video_pid; +#if WITH_H264 + static VideoStreamType ePrevType = vst_Unknown; +#endif myprintf(TEXT("Chaine::branche SID=%i, TSID=%i, ONID=%i, freq=%i\n"), SID, TSID, ONID, khz); @@ -203,13 +206,27 @@ if (pid) { switch (video_type) { case vst_MPEG2: +#if WITH_H264 + if (pVMR && ePrevType!=vst_MPEG2) { + if (FAILED(hr = switch_codec(pVideoCodec, TEXT("MPEG2")))) + return hr; + ePrevType = vst_MPEG2; + } +#endif hr = branche_pid(pMapMPEG2, pid IF_DEBUG_CB("Vidéo MPEG2")); break; -#ifdef TEST_H264 + +#if WITH_H264 case vst_H264: + if (pVMR && ePrevType!=vst_H264) { + if (FAILED(hr = switch_codec(pVideoH264Codec, TEXT("H264")))) + return hr; + ePrevType = vst_H264; + } hr = branche_pid(pMapH264, pid IF_DEBUG_CB("Vidéo H264")); break; #endif + default: hr=E_FAIL; } @@ -453,6 +470,9 @@ { if (!suspendu) { debranche_tous_pids(pMapMPEG2 IF_DEBUG_CB("Vidéo MPEG2")); +#if WITH_H264 + debranche_tous_pids(pMapH264 IF_DEBUG_CB("Vidéo H264")); +#endif debranche_son(); debranche_tous_pids(pMapPmt IF_DEBUG_CB("PMT")); suspendu = true; @@ -466,19 +486,31 @@ **/ bool rebranche(bool reset_son) { - // Note : l'initialisation du VMR est en principe ici déjà faite (ce qui fait - // que cet appel sera sans doute sans effet), mais ceci réserve la possibilité - // de retarder cet appel jusqu'au 1er branchement des flux .... le jour où - // j'aurai trouvé pourquoi cela pose problème ! - Gingko - if (do_init_vmr()) { + static bool bProt = false; // Protection contre la réentrance + bool bRes = false; - if (suspendu) { - suspendu = false; - Canaux[ixChaineCourante].branche(reset_son); + if (!bProt) { + bProt = true; + + // Note : l'initialisation du VMR est en principe ici déjà faite (ce qui fait + // que cet appel sera sans doute sans effet), mais ceci réserve la possibilité + // de retarder cet appel jusqu'au 1er branchement des flux .... le jour où + // j'aurai trouvé pourquoi cela pose problème ! - Gingko + if (do_init_vmr()) { + + if (suspendu) { + suspendu = false; + HRESULT hr = Canaux[ixChaineCourante].branche(reset_son); + + if (FAILED(hr)) + affiche_erreurs(TEXT("Erreur lors du rebranchement des sorties"), hr); + } + bRes = true; } - return true; + bProt = false; } - return false; + + return bRes; } /** Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/graph.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -51,6 +51,9 @@ CComPtr pDemux; CComPtr pVideoCodec; +#if WITH_H264 +CComPtr pVideoH264Codec; +#endif CComPtr pAudioCodec; CComPtr pAc3Codec; @@ -72,6 +75,8 @@ CComPtr pBDAFreq; CComPtr pStats; + +static bool bGraphPaused = false; //!< Événement "EC_PAUSED" reçu #if EXPORT_GRAPH static DWORD pdwRegister; @@ -166,6 +171,9 @@ pGraph.Release(); pVideoCodec.Release(); +#if WITH_H264 + pVideoH264Codec.Release(); +#endif pAudioCodec.Release(); pAc3Codec.Release(); @@ -239,7 +247,7 @@ static HRESULT connect_pin_to_filter(CComPtr & pOutPin, CComPtr & pFilter) { CComPtr pInPin; - HRESULT hr = cherche_pin(pFilter, PINDIR_INPUT, pInPin); + HRESULT hr = cherche_pin(pFilter, PINDIR_INPUT, pInPin, NOTCONNECTED); if (SUCCEEDED(hr)) hr = pGraph->ConnectDirect(pOutPin, pInPin, NULL); @@ -361,6 +369,20 @@ return !pStats ? E_NOINTERFACE : hr; } +/// Obtenir une broche de sortie du démultiplexeur +static HRESULT get_output_pin(IMpeg2Demultiplexer * pMpeg2Demux, + const AM_MEDIA_TYPE & am, LPCWSTR pszPinName, CComPtr & pOutPin) +{ + HRESULT hr; + + // Note : utilisation de "const_cast" ici car on ne s'attend pas normalement à ce que + // "CreateOutputPin" modifie les objets pointés. + hr = pMpeg2Demux->CreateOutputPin(const_cast(&am), + const_cast(pszPinName), &pOutPin); + myprintf(TEXT("%?Broche créée pour \"%") W2t TEXT("\"\n"), SUCCEEDED(hr), pszPinName); + return hr; +} + static HRESULT render_mp2v(IMpeg2Demultiplexer * pMpeg2Demux) { if (filtreMPEG2[0] == 0) { @@ -368,7 +390,10 @@ return S_OK; } - MPEG2VIDEOINFO mvi = { + if (IsNullCodec(filtreMPEG2)) + return S_OK; + + static const MPEG2VIDEOINFO mvi = { { // hdr {0,0,720,576}, // rcSource {0,0,0,0}, // rcTarget @@ -377,7 +402,7 @@ 0, // AvgTimePerFrame; 0, // dwInterlaceFlags; 0, // dwCopyProtectFlags; - 4, // dwPictAspectRatioX; + 4, // dwPictAspectRatioX; 3, // dwPictAspectRatioY {0}, // dwControlFlag & dwReserved1 0, // dwReserved2 @@ -390,7 +415,7 @@ } }; - AM_MEDIA_TYPE am = { + static const AM_MEDIA_TYPE am = { MEDIATYPE_Video, // majortype MEDIASUBTYPE_MPEG2_VIDEO, // subtype FALSE, // bFixedSizeSamples @@ -399,11 +424,11 @@ FORMAT_MPEG2Video, // formattype NULL, // pUnk sizeof(mvi), // cbFormat - (BYTE *)&mvi // pbFormat + (LPBYTE)&mvi // pbFormat }; CComPtr pVideoPin; - HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"video", &pVideoPin); + HRESULT hr = get_output_pin(pMpeg2Demux, am, L"video", pVideoPin); if (FAILED(hr)) return erreur(TEXT("La broche vidéo MPEG2 n'a pas pu être créée"), hr); @@ -434,32 +459,116 @@ return hr; } +#if WITH_H264 + +static HRESULT render_h264(IMpeg2Demultiplexer * pMpeg2Demux) +{ + if (filtreH264[0] == 0) { + affiche_erreurs(TEXT("Aucun codec vidéo H264 n'a été sélectionné")); + return S_OK; + } + + if (IsNullCodec(filtreH264)) + return S_OK; + + #define FCC_AVC1 MAKEFOURCC('A', 'V', 'C', '1') // Possible aussi ... + #define FCC_h264 MAKEFOURCC('h', '2', '6', '4') + #define DIMH 720 + #define DIMV 576 + + static const VIDEOINFOHEADER2 hdr = { + {0,0,0,0}, // rcSource + {0,0,0,0}, // rcTarget + 0, // dwBitRate, + 0, // dwBitErrorRate + 0, // AvgTimePerFrame + 0, // dwInterlaceFlags + 0, // dwCopyProtectFlags + 0, // dwPictAspectRatioX + 0, // dwPictAspectRatioY + {0}, // dwControlFlag & dwReserved1 + 0, // dwReserved2 + { // bmiHeader + sizeof(BITMAPINFOHEADER), // biSize + DIMH, // biWidth + DIMV, // biHeight + 0, // biPlanes, + 0, // biBitCount, + FCC_h264 // biCompression ( FCC_AVC1 ? ) + } + // le reste à zéro (implicite) + }; + + static const AM_MEDIA_TYPE am = { + MEDIATYPE_Video, // majortype + MEDIASUBTYPE_H264, // subtype + FALSE, // bFixedSizeSamples + TRUE, // bTemporalCompression + 1, // lSampleSize + FORMAT_VideoInfo2, // formattype + NULL, // pUnk + sizeof(hdr), // cbFormat + (LPBYTE)&hdr // pbFormat + }; + + CComPtr pVideoPin; + HRESULT hr = get_output_pin(pMpeg2Demux, am, L"h264", pVideoPin); + + if (FAILED(hr)) + return erreur(TEXT("La broche vidéo H264 n'a pas pu être créée"), hr); + + // le décodeur vidéo + hr = get_and_add_codec(filtreH264, MEDIATYPE_Video, MEDIASUBTYPE_H264, + TEXT("vidéo H264"), pVideoH264Codec); + if (SUCCEEDED(hr)) { + hr = connect_pin_to_filter(pVideoPin, pVideoH264Codec); + if (FAILED(hr)) + return erreur(TEXT("Impossible de connecter le démultiplexeur au codec vidéo H264 \"%s\""), hr, filtreH264); + } else { +#if AUTO_RENDER + hr = pGraph->RenderEx(pVideoPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); + if (FAILED(hr)) +#endif + affiche_erreurs(TEXT("Pas de rendu possible depuis la broche vidéo H264"), hr); + } + + hr = pVideoPin.QueryInterface(&pMapH264); + myprintf(TEXT("%?erreur pMapH264, hr=0x%08x\n"), FAILED(hr), hr); + + return hr; +} + +#endif // WITH_H264 + static HRESULT render_son(IMpeg2Demultiplexer * pMpeg2Demux) { - AM_MEDIA_TYPE am; - am.majortype = MEDIATYPE_Audio; - am.subtype = MEDIASUBTYPE_MPEG2_AUDIO; - am.bFixedSizeSamples = TRUE; - am.bTemporalCompression = FALSE; - am.lSampleSize = 0; - am.pUnk = NULL; + if (IsNullCodec(filtreAudio)) + return S_OK; - WAVEFORMATEX wfm; + static const WAVEFORMATEX wfm = { + WAVE_FORMAT_PCM, // wFormatTag + 2, // nChannels + 48000, // nSamplesPerSec + 4*48000, // nAvgBytesPerSec + 4, // nBlockAlign + 16, // wBitsPerSample + 0 // cbSize + }; - am.formattype = FORMAT_WaveFormatEx; - am.cbFormat = sizeof(WAVEFORMATEX); - am.pbFormat = (BYTE *)&wfm; + static const AM_MEDIA_TYPE am = { + MEDIATYPE_Audio, // majortype + MEDIASUBTYPE_MPEG2_AUDIO, // subtype + TRUE, // bFixedSizeSamples + FALSE, // bTemporalCompression + 0, // lSampleSize + FORMAT_WaveFormatEx, // formattype + NULL, // pUnk + sizeof(wfm), // cbFormat + (LPBYTE)&wfm // pbFormat + }; - wfm.wFormatTag = WAVE_FORMAT_PCM; - wfm.nChannels = 2; - wfm.nSamplesPerSec = 48000; - wfm.nBlockAlign = 4; - wfm.nAvgBytesPerSec = wfm.nBlockAlign * wfm.nSamplesPerSec; - wfm.wBitsPerSample = 16; - wfm.cbSize = 0; - CComPtr pSoundPin; - HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"son", &pSoundPin); + HRESULT hr = get_output_pin(pMpeg2Demux, am, L"son", pSoundPin); if (FAILED(hr)) return erreur(TEXT("La broche audio MPEG2 n'a pas pu être créée"), hr); @@ -501,31 +610,33 @@ static HRESULT render_ac3(IMpeg2Demultiplexer * pMpeg2Demux) { + if (IsNullCodec(filtreAc3)) + return S_OK; - AM_MEDIA_TYPE am; - am.majortype = MEDIATYPE_Audio; - am.subtype = MEDIASUBTYPE_DOLBY_AC3; - am.bFixedSizeSamples = TRUE; - am.bTemporalCompression = FALSE; - am.lSampleSize = 0; - am.pUnk = NULL; + static const WAVEFORMATEX wfm = { + WAVE_FORMAT_PCM, // wFormatTag + 2, // nChannels + 48000, // nSamplesPerSec + 48000*4, // nAvgBytesPerSec + 4, // nBlockAlign + 16, // wBitsPerSample + 0 // cbSize + }; - WAVEFORMATEX wfm; + static const AM_MEDIA_TYPE am = { + MEDIATYPE_Audio, // majortype + MEDIASUBTYPE_DOLBY_AC3, // subtype + TRUE, // bFixedSizeSamples + FALSE, // bTemporalCompression + 0, // lSampleSize + FORMAT_WaveFormatEx, // formattype + NULL, // pUnk + sizeof(wfm), // cbFormat + (LPBYTE)&wfm, // pbFormat + }; - am.formattype = FORMAT_WaveFormatEx; - am.cbFormat = sizeof(WAVEFORMATEX); - am.pbFormat = (BYTE *)&wfm; - - wfm.wFormatTag = WAVE_FORMAT_PCM; - wfm.nChannels = 2; - wfm.nSamplesPerSec = 48000; - wfm.nBlockAlign = 4; - wfm.nAvgBytesPerSec = wfm.nBlockAlign * wfm.nSamplesPerSec; - wfm.wBitsPerSample = 16; - wfm.cbSize = 0; - CComPtr pAc3Pin; - HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"ac3", &pAc3Pin); + HRESULT hr = get_output_pin(pMpeg2Demux, am, L"ac3", pAc3Pin); if (FAILED(hr)) return erreur(TEXT("La broche audio AC3 n'a pas pu être créée"), hr); @@ -567,20 +678,20 @@ static HRESULT render_psi(IMpeg2Demultiplexer * pMpeg2Demux) { - AM_MEDIA_TYPE am = { - MEDIATYPE_MPEG2_SECTIONS, // majortype - MEDIASUBTYPE_MPEG2DATA, // subtype - TRUE, // bFixedSizeSamples - FALSE, // bTemporalCompression - 0, // lSampleSize - FORMAT_None, // formattype - NULL, // pUnk - 0, // cbFormat - NULL // pbFormat + static const AM_MEDIA_TYPE am = { + MEDIATYPE_MPEG2_SECTIONS, // majortype + MEDIASUBTYPE_MPEG2DATA, // subtype + TRUE, // bFixedSizeSamples + FALSE, // bTemporalCompression + 0, // lSampleSize + FORMAT_None, // formattype + NULL, // pUnk + 0, // cbFormat + NULL // pbFormat }; CComPtr pDataPin; - HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"data", &pDataPin); + HRESULT hr = get_output_pin(pMpeg2Demux, am, L"data", pDataPin); if (FAILED(hr)) { erreur(TEXT("La broche PSI n'a pas pu être créée"), hr); @@ -614,21 +725,20 @@ static HRESULT render_epgfilter(IMpeg2Demultiplexer * pMpeg2Demux) { + static const AM_MEDIA_TYPE am = { + MEDIATYPE_MPEG2_SECTIONS, // majortype + MEDIASUBTYPE_DVB_SI, // subtype + TRUE, // bFixedSizeSamples + FALSE, // bTemporalCompression + 0, // lSampleSize + FORMAT_None, // formattype + NULL, // pUnk + 0, // cbFormat + NULL, // pbFormat + }; - AM_MEDIA_TYPE am; - am.majortype = MEDIATYPE_MPEG2_SECTIONS; - am.subtype = MEDIASUBTYPE_DVB_SI; - am.bFixedSizeSamples = TRUE; - am.bTemporalCompression = FALSE; - am.lSampleSize = 0; - am.pUnk = NULL; - - am.formattype = FORMAT_None; - am.cbFormat = 0; - am.pbFormat = NULL; - CComPtr pEpgPin; - HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"epg", &pEpgPin); + HRESULT hr = get_output_pin(pMpeg2Demux, am, L"epg", pEpgPin); if (FAILED(hr)) { erreur(TEXT("La broche EPG n'a pas pu être créée"), hr); @@ -661,20 +771,20 @@ static HRESULT render_pmtfilter(IMpeg2Demultiplexer * pMpeg2Demux) { - AM_MEDIA_TYPE am; - am.majortype = MEDIATYPE_MPEG2_SECTIONS; - am.subtype = MEDIASUBTYPE_DVB_SI; - am.bFixedSizeSamples = TRUE; - am.bTemporalCompression = FALSE; - am.lSampleSize = 0; - am.pUnk = NULL; + static const AM_MEDIA_TYPE am = { + MEDIATYPE_MPEG2_SECTIONS, // majortype + MEDIASUBTYPE_DVB_SI, // subtype + TRUE, // bFixedSizeSamples + FALSE, // bTemporalCompression + 0, // lSampleSize + FORMAT_None, // formattype + NULL, // pUnk + 0, // cbFormat + NULL // pbFormat + }; - am.formattype = FORMAT_None; - am.cbFormat = 0; - am.pbFormat = NULL; - CComPtr pPmtPin; - HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"pmt", &pPmtPin); + HRESULT hr = get_output_pin(pMpeg2Demux, am, L"pmt", pPmtPin); if (FAILED(hr)) return erreur(TEXT("La broche PMT n'a pas pu être créée"), hr); @@ -716,6 +826,11 @@ if (FAILED(hr = render_mp2v(pMpeg2Demux))) return erreur(TEXT("Erreur lors du rendu de la broche vidéo MPEG2"), hr); +#if WITH_H264 + if (FAILED(hr = render_h264(pMpeg2Demux))) + return erreur(TEXT("Erreur lors du rendu de la broche vidéo H264"), hr); +#endif + if (FAILED(hr = render_son(pMpeg2Demux))) return erreur(TEXT("Erreur lors du rendu de la broche audio MPEG2"), hr); @@ -748,7 +863,25 @@ if (!pControl) return E_NOINTERFACE; - return pControl->Run(); + + myprintf(TEXT("Démarrage du graphe\n")); + HRESULT hr = pControl->Run(); +#if WITH_H264 + if (FAILED(hr)) + return erreur(TEXT("Démarrage du graphe impossible"), hr); + if (hr==S_FALSE) { // Démarrage en instance : on attend que tout se stabilise + for (UINT nInx=0; nInx<10; nInx++) { // 10 * 200 mS = 2 secondes + Sleep(200); + if (graph_GetState()==State_Running) { + hr = S_OK; + break; + } + } + } +#endif + if (hr==S_OK) + bGraphPaused = false; + return hr; } /** @@ -774,6 +907,8 @@ if (!pControl) return E_NOINTERFACE; + bGraphPaused = false; + myprintf(TEXT("Arrêt du graphe\n")); return pControl->Stop(); } @@ -788,6 +923,9 @@ OAFilterState graph_GetState() { if (pGraph) { + if (bGraphPaused) + return State_Paused; + CComQIPtr pControl(pGraph); OAFilterState state; @@ -806,9 +944,9 @@ // Get all the events long evCode; + bool bSendTuneCmd = false; 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 @@ -887,26 +1025,29 @@ #if USE_CONSOLE case EC_ERRORABORT: // 0x03 - AMGetErrorText(HRESULT(param1), buffer, _countof(buffer)); - // Note : AMGetErrorText semble produire son propre saut de ligne - myprintf(TEXT("EC_ERRORABORT, raison=%08x: %s"), HRESULT(param1), buffer); + myprintf(TEXT("EC_ERRORABORT, raison=%08x: %s\n"), HRESULT(param1), + GetErrorText(HRESULT(param1)).c_str()); break; +#endif case EC_PAUSED: - AMGetErrorText(HRESULT(param1), buffer, _countof(buffer)); - // Note : AMGetErrorText semble produire son propre saut de ligne - myprintf(TEXT("EC_PAUSED, raison=%08x: %s"), HRESULT(param1), buffer); +#if USE_CONSOLE + myprintf(TEXT("EC_PAUSED, raison=%08x: %s\n"), HRESULT(param1), + GetErrorText(HRESULT(param1)).c_str()); +#endif + bGraphPaused = true; + bSendTuneCmd = true; break; -#endif case EC_VIDEO_SIZE_CHANGED: // 0x0a PostMessage(hWnd, WM_APP_VIDEOSIZE_CHG, 0, 0); myprintf(TEXT("Nouvelle taille vidéo = %u/%u\n"), LOWORD(param1), HIWORD(param1)); break; - } pEvents->FreeEventParams(evCode, param1, param2); } + if (bSendTuneCmd) + PostMessage(hWnd, WM_COMMAND, IDM_CHAN_TUNE, 0); return S_OK; } @@ -942,7 +1083,7 @@ CComPtr pNetworkProvider = dynamic_cast(CNetworkProvider::CreateInstance(NULL, &hr)); - + if (SUCCEEDED(hr)) hr = AddFilterToGraph(pNetworkProvider, CNetworkProvider::szFilterName); if (FAILED(hr)) Modifié: trunk/graph.h =================================================================== --- trunk/graph.h 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/graph.h 2009-02-21 22:44:54 UTC (rev 173) @@ -89,6 +89,9 @@ extern CComPtr pBDAFreq; extern CComPtr pMapMPEG2; +#if WITH_H264 +extern CComPtr pMapH264; +#endif extern CComPtr pMapSound; extern CComPtr pMapAc3; extern CComPtr pMapPmt; @@ -97,6 +100,9 @@ extern CComPtr pDSoundAc3; extern CComPtr pVideoCodec; +#if WITH_H264 +extern CComPtr pVideoH264Codec; +#endif extern CComPtr pAudioCodec; extern CComPtr pAc3Codec; Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/ini.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -124,6 +124,7 @@ // ==================================================================================== TCHAR filtreMPEG2[256]; +TCHAR filtreH264[256]; TCHAR filtreAudio[256]; TCHAR filtreAc3[256]; TCHAR nomVille[256]; @@ -224,6 +225,7 @@ static TCHAR ini_config[] = TEXT("Config"); ///< Nom de la section contenant la configuration static TCHAR ini_filtre_MPEG2[] = TEXT("Filtre MPEG2"); +static TCHAR ini_filtre_H264[] = TEXT("Filtre H264"); static TCHAR ini_filtre_audio[] = TEXT("Filtre audio"); static TCHAR ini_filtre_ac3[] = TEXT("Filtre AC3"); static TCHAR ini_nom_ville[] = TEXT("Ville"); @@ -1283,6 +1285,7 @@ save_driver_str(ini_receiver, nom_receiver); save_config_int(ini_offset_tuner, offset_tuner); save_driver_str(ini_filtre_MPEG2, filtreMPEG2); + save_driver_str(ini_filtre_H264, filtreH264); save_driver_str(ini_filtre_audio, filtreAudio); save_driver_str(ini_filtre_ac3, filtreAc3); save_config_str(ini_nom_ville, nomVille); @@ -1587,6 +1590,7 @@ load_driver_str(ini_receiver, nom_receiver, _countof(nom_receiver)); load_driver_str(ini_filtre_MPEG2, filtreMPEG2, _countof(filtreMPEG2)); + load_driver_str(ini_filtre_H264, filtreH264, _countof(filtreH264)); offset_tuner = load_config_int(ini_offset_tuner, 0); Modifié: trunk/ini.h =================================================================== --- trunk/ini.h 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/ini.h 2009-02-21 22:44:54 UTC (rev 173) @@ -30,6 +30,9 @@ #include "utils.h" #include "channels.h" +/// Activation ou désactivation de la fonctionnalité expérimentale H264 : +#define WITH_H264 1 + /** * Activation (1) ou désactivation (0) de la sauvegarde des informations * sur les flux vidéos, son et autre/ @@ -111,6 +114,7 @@ **/ extern TCHAR filtreMPEG2[256]; //!< Nom du codec Audio MPEG2 choisi +extern TCHAR filtreH264[256]; //!< Nom du codec H264, utilisé pour la HD 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 Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/main.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -303,13 +303,14 @@ int ixGrabber = getGrabberChaine(ixChaineCourante); bool curChannelRecording = ixGrabber != -1; bool freeGrabberAvailable = getFreeGrabber() != -1; + bool isMpeg2 = ixChaine_ok(ixChaineCourante) && Canaux[ixChaineCourante].video_type==vst_MPEG2; bool active; // Items d'enregistrement de la chaîne courante : ces items sont actifs // si la chaîne courante n'est pas déjà en cours d'enregistrement, et si // le nombre maximal de chaînes enregistrées n'est pas atteint. active = freeGrabberAvailable && !curChannelRecording; - set_menu_enable_state(hRecMenu, IDM_RECORD_CHANNEL_PS, active); + set_menu_enable_state(hRecMenu, IDM_RECORD_CHANNEL_PS, active && isMpeg2); set_menu_enable_state(hRecMenu, IDM_RECORD_CHANNEL_TS, active); // Enregistrement du multiplex : cette fonctionnalité doit être activée @@ -815,7 +816,7 @@ } if (!use_osd) { - _stprintf_s(str, TEXT("%s %i"), muted ? TEXT("Volume") : TEXT("Sourdine"), volumeCourant); + _stprintf_s(str, TEXT("%s %i"), muted ? TEXT("Sourdine") : TEXT("Volume"), volumeCourant); SendMessage(hMainStatus, SB_SETTEXT, 5, (LPARAM)str); } } @@ -1473,6 +1474,12 @@ create_property_dialog(pVideoCodec, filtreMPEG2); break; +#if WITH_H264 + case IDM_H264: + create_property_dialog(pVideoH264Codec, filtreH264); + break; +#endif + case IDM_AUDIO: create_property_dialog(pAudioCodec, filtreAudio); break; @@ -2684,6 +2691,9 @@ return -1; } } else { + /* // Désactivé (remplacé par resyntonisation sur + // événement "EC_PAUSED" dans le graphe) + if (verif_freq_demarrage && ixChaine_ok(ixChaineCourante)) { int nbChaines = (int)Canaux.size(); long freq_courante = Canaux[ixChaineCourante].khz; @@ -2704,6 +2714,8 @@ myprintf(TEXT("change_chaine(%u)\n"), ixChaineSauve); change_chaine(ixChaineSauve); } + */ + myprintf(TEXT("Branchement des sorties audio et vidéo\n")); // Branchement initial des sorties audio et vidéo : @@ -2863,6 +2875,10 @@ if (!CreateMainWindow(nCmdShow, cmdOptions && cmdOptions->bMinimize)) return -1; +#if WITH_H264==0 + DeleteMenu(hMainMenu, IDM_H264, MF_BYCOMMAND); +#endif + int nRetCode; do { Modifié: trunk/network.cpp =================================================================== --- trunk/network.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/network.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -81,14 +81,14 @@ *phr = E_OUTOFMEMORY; else { *phr = S_OK; - myprintf(TEXT("%s construit\n"), szFilterName); + myprintf(TEXT("CNetworkProvider::CNetworkProvider : %s construit\n"), szFilterName); } } } CNetworkProvider::~CNetworkProvider() { - myprintf(TEXT("%s detruit\n"), szFilterName); + myprintf(TEXT("CNetworkProvider::~CNetworkProvider() : %s detruit\n"), szFilterName); delete m_bidon; } Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/recprog.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -259,6 +259,14 @@ } const Chaine & canal = Canaux[ixChaine]; + + if (methode==meth_PS && canal.video_type!=vst_MPEG2) { + affiche_erreurs( + TEXT("L'enregistrement d'une chaîne H264 (cas de la haute définition) ") + TEXT("en mode PS n'est pas encore implémenté")); + return false; + } + int nbProgrammes = (int)Programmes.size(); for(int i = 0; i < nbProgrammes; i++) { Modifié: trunk/rendering.cpp =================================================================== --- trunk/rendering.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/rendering.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -520,6 +520,9 @@ /// Connexion à une sortie de codec HRESULT CVideoMixingRenderer::Connect(CComPtr & pVidCodec) { + if (bConnected) + return S_OK; // Déjà connecté + HRESULT hr = E_FAIL; if (pVidCodec) { @@ -534,7 +537,8 @@ TEXT("Veuillez le libérer et relancer l'application"), hr); hr = S_OK; - } + } else + bConnected = true; } else { erreur(TEXT("Il n'y a pas de codec vidéo disponible"), hr); @@ -543,6 +547,30 @@ return hr; } +#if WITH_H264 +/// Déconnexion +HRESULT CVideoMixingRenderer::Disconnect() +{ + if (!bConnected) + return S_OK; // Déjà déconnecté + + CComPtr pInPin; + CComPtr pOutPin; + HRESULT hr; + + if (FAILED(hr = cherche_pin(*this, PINDIR_INPUT, pInPin))) + return hr; + if (FAILED(hr = pInPin->ConnectedTo(&pOutPin))) + return hr; + if (FAILED(hr = pGraph->Disconnect(pOutPin))) + return hr; + if (FAILED(hr = pGraph->Disconnect(pInPin))) + return hr; + bConnected = false; + return hr; +} +#endif + /// Récupération du ratio d'aspect courant POINT CVideoMixingRenderer::GetAspectRatio() const { @@ -1357,19 +1385,6 @@ dwLastOsdSet = dwTicks; } -/// Texte issu de l'exemple VMR9 à partir duquel cette implémentation VMR9 -/// a été réalisée. -/// \todo Envisager traduction et affichage à un endroit plus approprié, -/// ou bien supprimer totalement -#define STR_VMR_DISPLAY_WARNING \ - TEXT("The VMR9 requires Direct3D9 in order to perform alpha blending. ") \ - TEXT("Therefore, this sample requires that your display be set to a mode ") \ - TEXT("which is compatible with your computer's video card. ") \ - TEXT("Most video cards support Direct3D in 16-bit and 32-bit RGB modes, ") \ - TEXT("and some newer cards support 16, 24 and 32-bit display modes.\r\n\r\n") \ - 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, bool bLast) { OsdRefs sRefs; @@ -1406,7 +1421,7 @@ // Give the bitmap to the VMR for display 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); + myprintf(TEXT("%?Échec SetAlphaBitmap (DrawOsdText) hr=0x%08x\n"), FAILED(hr), hr); } SelectObject(hdcBmp, hbmOld); @@ -1424,7 +1439,7 @@ 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); + myprintf(TEXT("%?Échec SetAlphaBitmap (ClearOsd) hr=0x%08x\n"), FAILED(hr), hr); // Effacement du bitmap qui était conservé en mémoire : ClearBitmap(); @@ -1489,7 +1504,9 @@ hr = pVMR->Init(); if (SUCCEEDED(hr)) { +#if WITH_H264==0 hr = pVMR->Connect(pVideoCodec); +#endif if (SUCCEEDED(hr) && eState==State_Running) hr = graph_Run(); } @@ -1517,7 +1534,37 @@ } } +#if WITH_H264 /** + * Débranchement du codec connecté au VMR, et branchement d'un nouveau + * \param[in] pFilter Nouveau codec à insérer + * \param[in] infotype Information de type de codec vidéo à inclure + * dans certains messages d'erreur + * \return Code d'erreur DirectShow + **/ +HRESULT switch_codec(CComPtr & pFilter, LPCTSTR infotype) +{ + HRESULT hr = S_OK; + + if (pVMR) { // si pas déjà initialisé + OAFilterState eSavState = graph_GetState(); + + if (/*true ||*/ eSavState!=State_Stopped) { + if ((hr = graph_Stop())!=S_OK) + return erreur(TEXT("Arrêt du graphe impossible"), hr); + } + if (FAILED(hr = pVMR->Disconnect())) + return erreur(TEXT("Erreur lors du retrait du codec vidéo précédent"), hr); + if (FAILED(hr = pVMR->Connect(pFilter))) + return erreur(TEXT("Erreur lors de l'ajout du codec vidéo %s"), hr, infotype); + if ((hr = graph_Run())!=S_OK) + return erreur(TEXT("Redémarrage du graphe impossible"), hr); + } + return hr; +} +#endif + +/** * 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/rendering.h =================================================================== --- trunk/rendering.h 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/rendering.h 2009-02-21 22:44:54 UTC (rev 173) @@ -62,6 +62,7 @@ { CComPtr pInputPin; //!< Interface sur la broche d'entrée DWORD last_tick; + bool bConnected; protected: /// Création et ajout du VMR dans le filtre virtual HRESULT CreateAndAdd() = 0; @@ -89,7 +90,8 @@ public: /// Constructeur CVideoMixingRenderer() : - last_tick(0) + last_tick(0), + bConnected(false) {} /// Définition du mode de ratio d'aspect. @@ -150,6 +152,11 @@ /// Connexion à une sortie de codec HRESULT Connect(CComPtr & pVidCodec); +#if WITH_H264 + /// Déconnexion + HRESULT Disconnect(); +#endif + /// Redessiner l'espace de la vidéo virtual void Paint(HDC hDC); @@ -463,7 +470,18 @@ **/ HRESULT init_vmr(); +#if WITH_H264 /** + * Débranchement du codec connecté au VMR, et branchement d'un nouveau + * \param[in] pFilter Nouveau codec à insérer + * \param[in] infotype Information de type de codec vidéo à inclure + * dans certains messages d'erreur + * \return Code d'erreur DirectShow + **/ +HRESULT switch_codec(CComPtr & pFilter, LPCTSTR infotype); +#endif + +/** * Nettoyage du VMR et de l'OSD **/ void clean_vmr(); Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/res.rc 2009-02-21 22:44:54 UTC (rev 173) @@ -74,6 +74,7 @@ POPUP "Fi<res" BEGIN MENUITEM "Codec &MPEG2...", IDM_MPEG2 + MENUITEM "C&odec H264...", IDM_H264 MENUITEM "Codec a&udio...", IDM_AUDIO MENUITEM "Codec &AC3...", IDM_AC3 MENUITEM SEPARATOR @@ -156,6 +157,8 @@ GROUPBOX "Codecs utilisés",IDC_STATIC,7,86,276,84 LTEXT "Codec MPEG2",IDC_STATIC,14,100,55,12,SS_CENTERIMAGE COMBOBOX IDC_COMBO_MPEG2,76,100,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Codec H264",IDC_COMBO_H264_S,14,116,55,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBO_H264,76,116,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP LTEXT "Codec Audio",IDC_STATIC,14,132,55,12,SS_CENTERIMAGE COMBOBOX IDC_COMBO_AUDIO,76,132,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP LTEXT "Codec AC3",IDC_STATIC,14,148,55,12,SS_CENTERIMAGE Modifié: trunk/resource.h =================================================================== --- trunk/resource.h 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/resource.h 2009-02-21 22:44:54 UTC (rev 173) @@ -77,6 +77,7 @@ #define IDC_VERIF_FREQ_START 1051 #define IDC_METHOD 1052 #define IDC_AUDIO 1053 +#define IDC_COMBO_H264_S 1058 // temporaire #define IDC_POUCHINTVMOD_URL 1059 #define IDC_PASWD 1060 #define IDC_AFTER 1061 Modifié: trunk/search.cpp =================================================================== --- trunk/search.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/search.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -28,6 +28,19 @@ #include "base.h" #include "search.h" +/** + * Détermine si une définition de codec est définie comme "Aucun" ("[Null]") ou + * "non défini" (chaîne vide). + * + * \param[in] pszName Nom du codec + * \retval \p true si aucun + * \retval \p false si défini + **/ +bool IsNullCodec(LPCTSTR pszName) +{ + return pszName[0]==0 || _tcscmp(pszName, NO_CODEC_NAME)==0; +} + // Structure d'assistance à la récupération d'une chaîne de caratères depuis une variable de type // VARIANT (permet en particulier de nettoyer la chaîne au passage, pour corriger un problème // constaté avec certains tuners): @@ -94,11 +107,7 @@ return hr; // Il y a eu une erreur à l'initialisation // Énumération des "monikers". - for ( - CComPtr pMoniker; - pEnum->Next(1, &pMoniker, NULL)==S_OK; - pMoniker.Release() - ) { + for (ENUM_ITF(pEnum, IMoniker, pMoniker)) { CComPtr pPropBag; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); @@ -125,13 +134,42 @@ } /** + * Vérification de la compatibilité d'une broche avec un type de média donné. + * \param[in] pPin Interface de la broche à tester + * \param[in] am Descripteur de type de média + * \retval \p true en cas de succès + **/ +bool check_pin_for_media(CComPtr & pPin, AM_MEDIA_TYPE & am) +{ + CComPtr pEnumMedia; + AM_MEDIA_TYPE * pmt; + bool found = false; + + for ( + pPin->EnumMediaTypes(&pEnumMedia); + !found && (pEnumMedia->Next(1, &pmt, NULL))==S_OK; + DeleteMediaType(pmt) + ) { + if (am.majortype == pmt->majortype && am.subtype == pmt->subtype) + found = true; + } + //if (pPin->QueryAccept(&am)==S_OK) { + // return true; + //} + return found; +} + +/** * 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 + * \param[in] pmt Si != \p NULL, alors la broche doit être non connectée, et si la valeur + * est différente de NOTCONNECTED, elle doit en plus accepter le média spécifié/ * \retval \p S_OK en cas de succès **/ -HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, CComPtr & result) +HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, + CComPtr & result, AM_MEDIA_TYPE * pmt) { // myprintf(TEXT("** cherche_pin\n")); CComPtr pEnumPins; @@ -152,20 +190,22 @@ pPin->QueryDirection(&direction); if (direction == dir) { -//#ifdef _DEBUG -// // write_pin_info(pPin); -// CComPtr connected; -// -// pPin->ConnectedTo(&connected); -// -// if (!connected) { -// result = pPin; -// break; -// } -//#else + if (pmt) { + // write_pin_info(pPin); + CComPtr connected; + + pPin->ConnectedTo(&connected); + + if (!connected) { + if (pmt==NOTCONNECTED || check_pin_for_media(pPin, *pmt)) { result = pPin; break; -//#endif + } + } + } else { + result = pPin; + break; + } } } @@ -183,11 +223,7 @@ pFilter->EnumPins(&pEnumPins); - for ( - CComPtr pPin; - eCompat==compat_None && pEnumPins->Next(1, &pPin, NULL)==S_OK; - pPin.Release() - ) { + for (ENUM_ITF(pEnumPins, IPin, pPin)) { PIN_DIRECTION dir; pPin->QueryDirection(&dir); @@ -211,6 +247,8 @@ DeleteMediaType(am); } + if (eCompat!=compat_None) + break; } return eCompat; @@ -238,11 +276,7 @@ return hr; // Il y a eu une erreur à l'initialisation // Énumération des "monikers". - for ( - CComPtr pMoniker; - pEnumMoniker->Next(1, &pMoniker, NULL)==S_OK; - pMoniker.Release() - ) { + for (ENUM_ITF(pEnumMoniker, IMoniker, pMoniker)) { CComPtr pPropBag; hr = pMoniker->BindToStorage(NULL, NULL, IID_IPropertyBag, (void **)&pPropBag); Modifié: trunk/search.h =================================================================== --- trunk/search.h 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/search.h 2009-02-21 22:44:54 UTC (rev 173) @@ -27,14 +27,31 @@ #pragma once +#define NO_CODEC_NAME TEXT("[null]") + +#define NOTCONNECTED ((AM_MEDIA_TYPE *)-1) + /** + * Détermine si une définition de codec est définie comme "Aucun" ("[Null]") ou + * "non défini" (chaîne vide). + * + * \param[in] pszName Nom du codec + * \retval \p true si aucun + * \retval \p false si défini + **/ +bool IsNullCodec(LPCTSTR pszName); + +/** * 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 + * \param[in] pmt Si != \p NULL, alors la broche doit être non connectée, et si la valeur + * est différente de NOTCONNECTED, elle doit en plus accepter le média spécifié/ * \retval \p S_OK en cas de succès **/ -HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, CComPtr & result); +HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, + CComPtr & result, AM_MEDIA_TYPE * pmt=NULL); /** * Classe d'assistance à l'énumération de codecs ayant des @@ -92,7 +109,9 @@ CSearchByType_FillCombo(GUID type, GUID subtype, bool bExactMatch, HWND hItm) : CSearchByType(type, subtype, bExactMatch), hItem(hItm) - {} + { + SendMessage(hItem, CB_ADDSTRING, 0, (LPARAM)TEXT("Aucun")); + } /** * Implémentation de méthode virtuelle appelée pour chaque codecs trouvé. Modifié: trunk/settings.cpp =================================================================== --- trunk/settings.cpp 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/settings.cpp 2009-02-21 22:44:54 UTC (rev 173) @@ -125,28 +125,32 @@ /** * Récupère la valeur textuelle sélectionnée dans la liste déroulante * - * \param[in] hItm handle de la liste déroulante dans la boite de dialogue - * \param[in,out] nom nom de la valeur précédement sélectionnée, et nouvelle valeur de celle-ci - * \param[in] size nombre de caractères dans la chaîne de caractères - * \retval true la sélection a été modifiée - * \retval false pas de changement de la sélection + * \param[in] hItm handle de la liste déroulante dans la boite de dialogue + * \param[in,out] nom nom de la valeur précédement sélectionnée, et nouvelle valeur de celle-ci + * \param[in] size nombre de caractères dans la chaîne de caractères + * \param[in] bWithNone \p true si l'item 0 indique "Aucun" + * \retval true la sélection a été modifiée + * \retval false pas de changement de la sélection **/ -static bool extrait_combo(HWND hItm, LPTSTR nom, size_t size) +static bool extrait_combo(HWND hItm, LPTSTR nom, size_t size, bool bWithNone) { // nom temporaire de l'élément sélectionné dans la liste déroulante TCHAR temp[256]; // Récupère l'index de l'élément sélectionné - LRESULT lRet; + INT nIdx = (INT)SendMessage(hItm, CB_GETCURSEL, 0, 0); - lRet = SendMessage(hItm, CB_GETLBTEXT, - SendMessage(hItm, CB_GETCURSEL, 0, 0), - (LPARAM)temp); + if (bWithNone && nIdx == 0) { + // "Aucun" + _tcscpy_s(temp, size, NO_CODEC_NAME); + } else { + LRESULT lRet = SendMessage(hItm, CB_GETLBTEXT, nIdx, (LPARAM)temp); - if(lRet == CB_ERR) - // La liste est vide :( - // ou aucun élément n'est sélectionné - return false; + if (lRet == CB_ERR) + // La liste est vide :( + // ou aucun élément n'est sélectionné + return false; + } if (_tcscmp(nom, temp)==0) return false; // false = Aucun changement @@ -1109,6 +1113,8 @@ static LRESULT remplit_combo_filtre(HWND hItm, GUID type, GUID subtype, LPCTSTR nom) { CSearchByType_FillCombo(type, subtype, exact_match, hItm).Do(); + if (IsNullCodec(nom)) + return SendMessage(hItm, CB_SETCURSEL, 0, 0); return SendMessage(hItm, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)nom); } @@ -1127,11 +1133,14 @@ BOOL valid = false; // Vérifié si des paramètres ont été changés, et récupère les nouvelles version - changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_TUNER), nom_tuner, _countof(nom_tuner)); - changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_RECEIVER), nom_receiver, _countof(nom_receiver)); - changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_MPEG2), filtreMPEG2, _countof(filtreMPEG2)); - changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_AUDIO), filtreAudio, _countof(filtreAudio)); - changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_AC3), filtreAc3, _countof(filtreAc3)); + changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_TUNER), nom_tuner, _countof(nom_tuner), false); + changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_RECEIVER), nom_receiver, _countof(nom_receiver), false); + changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_MPEG2), filtreMPEG2, _countof(filtreMPEG2), true); +#if WITH_H264 + changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_H264), filtreH264, _countof(filtreH264), true); +#endif + changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_AUDIO), filtreAudio, _countof(filtreAudio), true); + changed |= extrait_combo(GetDlgItem(hDlg, IDC_COMBO_AC3), filtreAc3, _countof(filtreAc3), true); // La valeur suivante n'est pas prise en compte dans le résultat de la fonction int res = (int)GetDlgItemInt(hDlg, IDC_TUNER_OFFSET, &valid, TRUE); @@ -1141,6 +1150,17 @@ // Récapitulatif des valeurs dans la fenêtre (pour debug uniquement) myprintf(TEXT("Tuner: %s\nReceiver: %s\nVideo: %s\nAudio: %s\nAc3: %s\nOffset: %i\n"), nom_tuner, nom_receiver, filtreMPEG2, filtreAudio, filtreAc3, offset_tuner); + +#if WITH_H264 + if (changed && _tcsstr(filtreMPEG2, TEXT("ffdshow")) && _tcsstr(filtreH264, TEXT("ffdshow"))) { + MessageBox(hDlg, + TEXT("L'utilisation du codec « ffdshow » pour, en même temps, les filtres MPEG2 ") + TEXT("et H264, n'est possible que si ce codec est configuré pour accepter les ") + TEXT("instances multiples, ce qui n'est PAS le cas par défaut. Une erreur 0x80004005 ") + TEXT("se produira en cas de mauvaise configuration."), + TEXT("Avertissement concernant le codec « ffdshow »"), MB_ICONWARNING); + } +#endif return changed; } @@ -1161,12 +1181,19 @@ HWND hTuner = GetDlgItem(hDlg, IDC_COMBO_TUNER); HWND hReceiver = GetDlgItem(hDlg, IDC_COMBO_RECEIVER); HWND hMpeg2 = GetDlgItem(hDlg, IDC_COMBO_MPEG2); + HWND hH264 = GetDlgItem(hDlg, IDC_COMBO_H264); HWND hAudio = GetDlgItem(hDlg, IDC_COMBO_AUDIO); HWND hAc3 = GetDlgItem(hDlg, IDC_COMBO_AC3); remplit_combo_tuner(hTuner, KSCATEGORY_BDA_NETWORK_TUNER, nom_tuner); remplit_combo_tuner(hReceiver, KSCATEGORY_BDA_RECEIVER_COMPONENT, nom_receiver); remplit_combo_filtre(hMpeg2, MEDIATYPE_Video, MEDIASUBTYPE_MPEG2_VIDEO, filtreMPEG2); +#if WITH_H264 + remplit_combo_filtre(hH264, MEDIATYPE_Video, MEDIASUBTYPE_H264, filtreH264); +#else + ShowWindow(hH264, SW_HIDE); + ShowWindow(GetDlgItem(hDlg, IDC_COMBO_H264_S), SW_HIDE); +#endif remplit_combo_filtre(hAudio, MEDIATYPE_Audio, MEDIASUBTYPE_MPEG2_AUDIO, filtreAudio); remplit_combo_filtre(hAc3, MEDIATYPE_Audio, MEDIASUBTYPE_DOLBY_AC3, filtreAc3); SetDlgItemInt(hDlg, IDC_TUNER_OFFSET, (UINT)offset_tuner, TRUE); @@ -1205,7 +1232,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)); @@ -1371,12 +1398,12 @@ // IDABORT = annulé après tentative de scan return TRUE; case _cmd_(IDOK, BN_CLICKED): - extrait_combo(hComboItem, nomVille, _countof(nomVille)); + extrait_combo(hComboItem, nomVille, _countof(nomVille), false); sauve_chaines(); // sauvegarde les chaînes dans le fichier xml EndDialog(hDlg, IDOK); // IDOK = pas d'erreur return TRUE; case _cmd_(IDC_COMBO_VILLE, CBN_SELCHANGE): - extrait_combo(hComboItem, nomVille, _countof(nomVille)); + extrait_combo(hComboItem, nomVille, _countof(nomVille), false); return TRUE; } return FALSE; @@ -1616,6 +1643,15 @@ case WM_COMMAND: switch(wParam) { + + case _cmd_(IDC_MOTIF_NOM_REC, EN_CHANGE): { + TCHAR szTmp[MAX_PATH]; + + SendMessage(hMotifNomsEnreg, WM_GETTEXT, (WPARAM)_countof(szTmp), (LPARAM)szTmp); + if (_tcscmp(motif_noms_enreg, szTmp)!=0) + PropSheet_Changed(GetParent(hDlg), hDlg); + return 0; } + case _cmd_(IDC_AVANCE_ENREG, EN_CHANGE): case _cmd_(IDC_RETARD_ENREG, EN_CHANGE): // Changement de l'offset @@ -1752,19 +1788,18 @@ BYTE fRepeat : 1 ; BYTE fUp : 1 ; } vTouche; + ZeroMemory(&vTouche, sizeof(vTouche)); vTouche.cRepeat = 1; vTouche.ScanCode = (BYTE)MapVirtualKey(shortcut.touche, 0); - if ( (touche >= VK_F1 && touche <= VK_F24) - ) + if ((touche >= VK_F1 && touche <= VK_F24)) vTouche.fExtended = 0; else vTouche.fExtended = 1; LONG codeTouche; memcpy_s(&codeTouche, sizeof(codeTouche), &vTouche, sizeof(codeTouche)); // Valeur de la touche - GetKeyNameText(codeTouche, szTouche, _countof(szTouche)); - } // default + GetKeyNameText(codeTouche, szTouche, _countof(szTouche)); } // default } _tcscat_s(buffer, taille, szTouche); } @@ -2011,13 +2046,13 @@ } if (valide) psn_result(hDlg, FALSE); - return FALSE; + return FALSE; } // case PSN_KILLACTIVE case PSN_RESET: // On a appuyé sur le bouton Annuler load_config_raccourcis(); - } // switch (_ncode_(lParam)) + } // switch (_ncode_(lParam)) if (hhook == 0 && p->hdr.idFrom == IDC_SHORTCUT) { // Notification envoyée de la liste des raccourcis @@ -2029,7 +2064,7 @@ p->ptAction // pt }; ListView_SubItemHitTest(hList, &lvhti); - + // On ne fait rien si on n'est pas dans la seconde/troisième colonne if (lvhti.iSubItem == SHORT_COL_RACCOURCIS || lvhti.iSubItem == SHORT_COL_ALTERNATIF) { // On mémorise la case sélectionnée @@ -2075,8 +2110,8 @@ TCHAR buffer[256]; GenerateTextualShorcut(*param, szRaccourci, _countof(szRaccourci)); - _stprintf_s(buffer, _countof(buffer), - TEXT("Le raccourci «%s» est déjà utilisé pour «%s».\n\nVoulez-vous le remplacer ?"), + _stprintf_s(buffer, _countof(buffer), + TEXT("Le raccourci «%s» est déjà utilisé pour «%s».\n\nVoulez-vous le remplacer ?"), szRaccourci, item.nom); if (MessageBox(hDlg, buffer, TEXT("Raccourci déjà existant"), MB_YESNO) == IDYES) { if (item.raccourci == *param) Modifié: trunk/utils.h =================================================================== --- trunk/utils.h 2009-02-18 07:30:27 UTC (rev 172) +++ trunk/utils.h 2009-02-21 22:44:54 UTC (rev 173) @@ -677,3 +677,13 @@ * - La fonction est capable de convertir des caractères codés sur plus de 16 bits **/ int ConvertChar2UTF8(UINT32 aconvertir, LPSTR & convertis); + +/** + * Macro d'assistance à l'énumération d'interface + **/ +#define ENUM_ITF(parent, type, name) \ + CComPtr name; \ + parent->Next(1, &name, NULL)==S_OK; \ + name.Release() + +// ---------------------------------------------------------------------------- From pouchintv-dev at baysse.fr Sun Feb 22 09:07:46 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sun, 22 Feb 2009 09:07:46 +0100 Subject: [Pouchintv-dev] =?iso-8859-1?q?Proposition_=3A_num=E9rotation_des?= =?iso-8859-1?q?_versions=2E?= References: <20090221224455.47D6C5F436@mail.baysse.fr> Message-ID: Bonjour, Je profite de la mise en ligne d'une première version HD pour faire les suggestions suivantes aux développeurs : 1) Laurent avait configuré un système de génération de versions qui simplifiait la numérotation, avec 4 chiffres : a) numéro majeur b) numéro mineur c) numéro SVN d) 0 normalement, 1 si modification locale (éventuellement 2, 3, 4, etc .... réservés) Ainsi, la version que je viens de mettre en ligne est numérotée 0.4.173.0 Je propose d'officialiser cette numérotation (voire même de l'appliquer rétroactivement à certaines versions) 2) Je propose aussi de profiter du passage à une version H264/HD pour incrémenter le numéro mineur à 0.5. Ainsi, la prochaine version pourrait être : 0.5.174.0 J'aimerais savoir ce que vous en pensez. Gingko From pouchintv-dev at baysse.fr Thu Feb 26 10:40:23 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Thu, 26 Feb 2009 10:40:23 +0100 Subject: [Pouchintv-dev] =?iso-8859-1?q?Proposition_=3A_num=E9rotation_des?= =?iso-8859-1?q?_versions=2E?= References: <20090221224455.47D6C5F436@mail.baysse.fr> Message-ID: <000c01c997f6$3fa92b10$4001a8c0@bunny> Bonjour, C'est parfait, ef15c ----- Original Message ----- From: "Liste utilisée par les développeurs" To: "Liste utilisée par les développeurs" Sent: Sunday, February 22, 2009 9:07 AM Subject: [Pouchintv-dev] Proposition : numérotation des versions. Bonjour, Je profite de la mise en ligne d'une première version HD pour faire les suggestions suivantes aux développeurs : 1) Laurent avait configuré un système de génération de versions qui simplifiait la numérotation, avec 4 chiffres : a) numéro majeur b) numéro mineur c) numéro SVN d) 0 normalement, 1 si modification locale (éventuellement 2, 3, 4, etc .... réservés) Ainsi, la version que je viens de mettre en ligne est numérotée 0.4.173.0 Je propose d'officialiser cette numérotation (voire même de l'appliquer rétroactivement à certaines versions) 2) Je propose aussi de profiter du passage à une version H264/HD pour incrémenter le numéro mineur à 0.5. Ainsi, la prochaine version pourrait être : 0.5.174.0 J'aimerais savoir ce que vous en pensez. Gingko _______________________________________________ Pouchintv-dev mailing list Pouchintv-dev at baysse.fr https://listes.baysse.fr/listinfo/pouchintv-dev From pouchintv-dev at baysse.fr Fri Feb 27 15:52:41 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Fri, 27 Feb 2009 15:52:41 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r174 - in trunk: . Icones/Belges Icones/Locales Message-ID: <20090227145241.0C61A5F436@mail.baysse.fr> Author: gingko Date: 2009-02-27 15:52:40 +0100 (ven, 27 fév 2009) New Revision: 174 Added: trunk/Icones/Belges/EURONEWS.bmp trunk/Icones/Locales/Terre d'infos.bmp Removed: trunk/Icones/Belges/euronews.bmp Modified: trunk/Icones/Locales/LM TV SARTHE.bmp trunk/Icones/Locales/ORLEANS TV.bmp trunk/Programme_Install.nsi trunk/base.h trunk/channels.cpp trunk/channels.h trunk/epg.cpp trunk/epgfilter.cpp trunk/graph.cpp trunk/ini.cpp trunk/main.cpp trunk/network.cpp trunk/parse.cpp trunk/res.rc trunk/resource.h trunk/search.h trunk/settings.cpp trunk/utils.cpp trunk/utils.h trunk/version Log: Passage à la version 0.5, premiers correctifs sur la version expérimentale HD. Modification dans l'EPG. version : * La version du programme passe de 0.4 à 0.5. epg.cpp, epgfilter.cpp, res.rc : * La mise à jour de la liste des programmes se fait maintenant en temps réel (plus besoin de presser de bouton "Mettre à jour"). * Le bouton "Mettre à jour" est, en conséquence supprimé. * En lieu et place, ajout d'un bouton "Réinitialiser", qui efface complètement la liste des programmes, ce qui provoque son rechargement intégral depuis le multiplex avec des données neuves. * La colonne "Description" (la dernière de la liste) a maintenant 1024 points de largeur au lieu de 700. graph.cpp : * Retrait d'une modification qui visait à mieux apprécier l'état de fonctionnement du graphe, mais ça ne donnait pas les résultats escomptés, amenant indirectement des conséquences indésirables telles que le non-démarrages d'enregistrements programmés chez certains utilisateurs. channels.cpp : * Les codecs définis comme "Aucun" ne sont pas connectés au démultiplexeur (mais aucun message d'erreur n'est renvoyé) settings.cpp, channels.h, channels.cpp : * Ajout de colonnes pour afficher les champs TsId, OnId, SId, vPId (pid vidéo), pPId (pid PMT) dans le dialogue de configuration des chaînes. Ces colonnes sont disposées à droite des colonnes existantes, de sorte qu'elles tombent en dehors de la zone d'affichage visible (et donc l'apparence immédiate change peu), et il faut utiliser la barre de défilement pour les voir. * Dans ce même dialogue, ainsi que dans la recherche de chaîne, la colonne "Mpeg" devient "norme", et la norme est maintenant affichée en clair (MPEG2 ou H264). main.cpp : * Factorisation et optimisation de l'affichage du nom de l'émission sous MSN. Ceci corrige probablement au passage un bug non rapporté, concernant l'effacement de ce nom, en compilation SBCS seulement. * Les pistes audio EAC3, non gérées actuellement, sont affichées désactivées. * En mode debugging, le dialogue d'affichage de l'état du graphe liste aussi tous les filtres présents. res.rc, settings.cpp, search.h : * Les listes de filtres sont triées par l'application plutôt que directement par le contrôle de liste déroulante. Ceci permet d'exclure du tri l'item "Aucun", qui doit apparaître systématiquement en premier. Du coup, les clases "CSearchByType_FillCombo" et "CSearchByCategory_FillCombo" sont modifiées pour sortir leurs résultats dans des tableaux de chaînes de caractères (dynamiques) plutôt que directement dans la liste déroulante, et sont renommées CSearchByType_FillVector et CSearchByCategory_FillVector respectivement. utils.h, utils.cpp : * Ajout de quelques fonctions et macros utilitaires (avec utilisation effective dans quelques autres fichiers). base.h : * Inclusion générique de quelques en-têtes ATL, et activation de l'espace de nom "std::" pour toute l'application. Programme_install.nsi : * Inclusion de l'installation des chaînes belges. * Les icônes belges et allemandes sont désactivées par défaut dans l'installation. Ajout d'une icône locale "Terre d'infos.cmp". Ajustement sur quelques autres icônes. Copié : trunk/Icones/Belges/EURONEWS.bmp (de révision 165, trunk/Icones/Belges/euronews.bmp) =================================================================== (les fichiers binaires diffèrent) Supprimé: trunk/Icones/Belges/euronews.bmp =================================================================== (les fichiers binaires diffèrent) Modifié: trunk/Icones/Locales/LM TV SARTHE.bmp =================================================================== (les fichiers binaires diffèrent) Modifié: trunk/Icones/Locales/ORLEANS TV.bmp =================================================================== (les fichiers binaires diffèrent) Ajouté: trunk/Icones/Locales/Terre d'infos.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Locales/Terre d'infos.bmp ___________________________________________________________________ Nom : svn:mime-type + application/octet-stream Modifié: trunk/Programme_Install.nsi =================================================================== --- trunk/Programme_Install.nsi 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/Programme_Install.nsi 2009-02-27 14:52:40 UTC (rev 174) @@ -246,12 +246,18 @@ File "Icones\Locales\*.bmp" SectionEnd - Section "Allemandes" IconesAllemendes + Section /o "Allemandes" IconesAllemandes SetOutPath "$INSTDIR\Icones\Allemandes" ;Ajout des icones des chaines locales File "Icones\Allemandes\*.bmp" SectionEnd + Section /o "Belges" IconesBelges + SetOutPath "$INSTDIR\Icones\Belges" + ;Ajout des icones des chaines locales + File "Icones\Belges\*.bmp" + SectionEnd + SectionGroupEnd Function .onInit Modifié: trunk/base.h =================================================================== --- trunk/base.h 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/base.h 2009-02-27 14:52:40 UTC (rev 174) @@ -76,8 +76,13 @@ #include #pragma warning(disable:4995) + #include +#include +#include +using namespace std; + // Le fichier "vstudio_edition.h" est le résultat d'un test (appelé depuis // le script "version.cmd") visant à savoir si l'environnement courant est // Visual C++ 2005 Express ou bien une des éditions Visual Studio 2005 complètes. Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/channels.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -81,16 +81,17 @@ return sons==cpmt.sons && autr==cpmt.autr; } -char ChainePMT::norme(void) const +LPCTSTR ChainePMT::norme(void) const { switch (video_type) { case vst_MPEG2: - return '2'; + return TEXT("Mpeg2"); case vst_H264: + return TEXT("H264"); case vst_H264_encrypted: - return '4'; + return TEXT("Crypt"); } - return '?'; + return TEXT("Inconnu"); } // Constructeur : @@ -366,7 +367,7 @@ if (canal.numeroChaine==0) canal.numeroChaine = nouveau_numero_chaine(); - if (canal.norme()!='2') + if (canal.video_type!=vst_MPEG2) canal.etat = ec_inactive; } } @@ -457,6 +458,9 @@ HRESULT branche_pid(CComPtr & pMap, ULONG pid IF_DEBUG_CB(LPCSTR nom_itf), MEDIA_SAMPLE_CONTENT eMsc) { + if (!pMap) // Filtre non défini : on ne branche rien et on retourne S_OK + return S_OK; + 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); Modifié: trunk/channels.h =================================================================== --- trunk/channels.h 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/channels.h 2009-02-27 14:52:40 UTC (rev 174) @@ -64,7 +64,7 @@ liste_pistes autr; ChainePMT(); - char norme(void) const; + LPCTSTR norme(void) const; bool operator == (const ChainePMT & cpmt) const; bool operator != (const ChainePMT & cpmt) const {return ! operator == (cpmt);}; }; Modifié: trunk/epg.cpp =================================================================== --- trunk/epg.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/epg.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -112,7 +112,7 @@ const Chaine & canal = Canaux[i]; if (canal.etat != ec_inactive) { - for (BYTE j=0; j<_countof(canal.emis); ++j) + for (BYTE j=0; jwVKey == VK_F5) - PostMessage(hDlg, WM_COMMAND, IDC_UPDATE, 0); + PostMessage(hDlg, WM_COMMAND, IDC_RESET_EPG, 0); } } return FALSE; } Modifié: trunk/epgfilter.cpp =================================================================== --- trunk/epgfilter.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/epgfilter.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -31,6 +31,7 @@ #include "channels.h" #include "crc32.h" #include "mpeg2defs.h" +#include "epg.h" CEPGFilter::CEPGFilter(IUnknown *pUnk, HRESULT *phr) : CBaseRenderer(__uuidof(this), WCHAR2TCHAR(szFilterName), pUnk, phr) @@ -73,16 +74,16 @@ CUnknown * WINAPI CEPGFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr) // static { - CEPGFilter *pNewFilter = new CEPGFilter(pUnk, phr); + CEPGFilter *pNewFilter = new CEPGFilter(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; } static void parse_eit(const SI_EIT & eit, size_t size) @@ -153,7 +154,10 @@ ++chaine.emi_count; // données mal initialisées depuis un autre thread) modif = true; } - + + if (modif) + PostMessage(hEpgDlg, WM_APP_EPG_UPDATED, 0, 0); + // passe par le thread graphique pour updater, sinon ça plante if (modif && ixChaine == ixChaineCourante) PostMessage(hMainWnd, WM_APP_EPG_UPDATED, 0, 0); Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/graph.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -76,7 +76,6 @@ CComPtr pStats; -static bool bGraphPaused = false; //!< Événement "EC_PAUSED" reçu #if EXPORT_GRAPH static DWORD pdwRegister; @@ -138,7 +137,8 @@ } #endif -void clean_dshow(void) { +void clean_dshow(void) +{ myprintf(TEXT("save ok\n")); @@ -168,7 +168,6 @@ pMpeg2Data.Release(); pEvents.Release(); - pGraph.Release(); pVideoCodec.Release(); #if WITH_H264 @@ -201,6 +200,7 @@ for (int i=0; i pVideoPin; @@ -879,8 +879,6 @@ } } #endif - if (hr==S_OK) - bGraphPaused = false; return hr; } @@ -907,7 +905,6 @@ if (!pControl) return E_NOINTERFACE; - bGraphPaused = false; myprintf(TEXT("Arrêt du graphe\n")); return pControl->Stop(); } @@ -923,9 +920,6 @@ OAFilterState graph_GetState() { if (pGraph) { - if (bGraphPaused) - return State_Paused; - CComQIPtr pControl(pGraph); OAFilterState state; @@ -1035,14 +1029,12 @@ myprintf(TEXT("EC_PAUSED, raison=%08x: %s\n"), HRESULT(param1), GetErrorText(HRESULT(param1)).c_str()); #endif - bGraphPaused = true; bSendTuneCmd = true; break; case EC_VIDEO_SIZE_CHANGED: // 0x0a PostMessage(hWnd, WM_APP_VIDEOSIZE_CHG, 0, 0); myprintf(TEXT("Nouvelle taille vidéo = %u/%u\n"), LOWORD(param1), HIWORD(param1)); - break; } pEvents->FreeEventParams(evCode, param1, param2); } Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/ini.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -34,7 +34,6 @@ #include "xml.h" #include -#include // pour 'sort' // ==================================================================================== // Variables externes Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/main.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -59,7 +59,8 @@ WORD numeroChaineSaisi = 0; -static bool muted = false; //!< Sourdine +static bool muted = false; //!< Sourdine +static bool msn_msg_set = false;//!< Message sous MSN placé /// Délai d'attente avant basculement des bordures #define DUREE_SWITCH_BORDER 400 @@ -422,7 +423,12 @@ _stprintf_s(tab, _countof(tab), TEXT("Audio %i %") A2t TEXT(" (%") A2t TEXT(")"), i+1, langue, son_courant.type > ast_EAC3 ? "???" : tblNomsAudio[son_courant.type]); - AppendMenu(pistes, (i==ixSonCourant) ? MF_CHECKED : MF_UNCHECKED, IDM_PISTES_BASE+i, tab); + + UINT nFlags = i==ixSonCourant ? MF_CHECKED : MF_UNCHECKED; + + if (son_courant.type==ast_EAC3) + nFlags|= MF_GRAYED; // E-AC3 non disponible pour le moment + AppendMenu(pistes, nFlags, IDM_PISTES_BASE+i, tab); } InsertMenu(hMenu, MENU_PISTES_POSITION, MF_BYPOSITION|MF_POPUP|MF_STRING, (UINT_PTR)pistes, nom_menu); @@ -783,8 +789,79 @@ } } -static void update_status_bar(void) +/** + * Envoi d'un message dans la fenêtre MSN + * \param[in] hMsnWnd Handle de la fenêtre MSN + * \param[in] pszMsg Message à envoyer + **/ +static LRESULT send_msn_msg(HWND hMsnWnd, LPCWSTR pszMsg) { + COPYDATASTRUCT msndata = { + 0x547, // dwData + (strlen_T(pszMsg)+1)*sizeof(WCHAR), // cbData + PVOID(pszMsg) // lpData + }; + + return SendMessage(hMsnWnd, WM_COPYDATA, (WPARAM)hMainWnd, (LPARAM)&msndata); +} + +/** + * Envoi du nom de la chaîne et de l'émission dans la fenêtre MSN, + * si l'option correspondante est active + * + * Infos : http://www.autoitscript.com/forum/index.php?showtopic=43112 + **/ +static void set_msn_msg() +{ + #define MSN_MAX_LENGTH 256 + + if (use_msn && ixChaine_ok(ixChaineCourante)) { + HWND hMsnWnd = FindWindow(TEXT("MsnMsgrUIManager"), NULL); + + if (hMsnWnd != NULL) { + WCHAR buffer[MSN_MAX_LENGTH]; + const Chaine & canal = Canaux[ixChaineCourante]; + + swprintf_s(buffer, _countof(buffer), + L"\\0Music\\01\\0{0} - {1}\\0%S\\0%" T2w L"\\0\\0\\0", + canal.nom, canal.getCurrentProgramName(TEXT("..."))); + + send_msn_msg(hMsnWnd, buffer); + msn_msg_set = true; + } + } +} + +/** + * Effacement du message préalablement envoyé dans la fenêtre MSN, + * s'il y en avait un de défini + **/ +static void reset_msn_msg() +{ + if (msn_msg_set) { + // On cherche la fenêtre + HWND hMsnWnd = FindWindow(TEXT("MsnMsgrUIManager"), NULL); + + // Si, hMsnWnd == NULL, MSN ne fonctionne pas ou la fenêtre est masquée (donc, pas de mise à jour) + if (hMsnWnd != NULL) { + // Si on l'a trouvée, on efface la "musique" indiquée sur MSN + send_msn_msg(hMsnWnd, L"\\0Music\\00\\0\\0\\0\\0\\0\\0"); + } + msn_msg_set = false; + } +} + +/** + * Mise à jour du message sous MSN et de l'icône de notification + **/ +static void update_msn_and_tip() +{ + set_msn_msg(); + niData.update_tip(); +} + +static void update_status_bar() +{ if (!ixChaine_ok(ixChaineCourante)) return; @@ -825,27 +902,6 @@ lcd.SetVolume(volumeCourant); lcd.ActualiseLcd(); #endif - - if (use_msn && canal_courant.emi_count > 0) { - HWND msnui = FindWindow(TEXT("MsnMsgrUIManager"), NULL); - - if (msnui != NULL) - { - COPYDATASTRUCT msndata; - WCHAR buffer[1024]; - - swprintf_s(buffer, _countof(buffer), - 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; - msndata.cbData = (lstrlenW(buffer)*2)+2; - SendMessage(msnui, WM_COPYDATA, (WPARAM)hMainWnd, (LPARAM)&msndata); - } - } - - niData.update_tip(); } /** @@ -861,6 +917,7 @@ if (hr==S_OK) { update_all_menus(hMainWnd); update_status_bar(); + update_msn_and_tip(); } return hr; } @@ -873,6 +930,7 @@ **/ void zappe_index(int ixChaine) { + myprintf(TEXT("\n##################### (début sélection chaîne) #########################\n")); if (pOSD) pOSD->Clear(); // Effacer tous les objets OSD courants @@ -1396,6 +1454,51 @@ } } +#ifdef _DEBUG +static void display_graph_state() +{ + myprintf(TEXT("Demande de l'état du graphe\n")); + + OAFilterState state = graph_GetState(); + CComPtr pEnumfilters; + tstring strState; + + pGraph->EnumFilters(&pEnumfilters); + + for (ENUM_ITF(pEnumfilters, IBaseFilter, pFilter)) { + HRESULT hr; + FILTER_INFO sInfo; + CComHeapPtr pszVendorInfo; + FILTER_STATE eState; + CLSID clsidFlt; + tstring strFlt; + + hr = pFilter->QueryFilterInfo(&sInfo); + hr = pFilter->QueryVendorInfo(&pszVendorInfo); + hr = pFilter->GetState(2000, &eState); + hr = pFilter->GetClassID(&clsidFlt); + + strFlt = tstr_printf(TEXT("\n- %") W2t, sInfo.achName); + if (pszVendorInfo) + strFlt += tstr_printf(TEXT(" [%") W2t TEXT("]"), pszVendorInfo.m_pData); + strFlt += tstr_printf(TEXT(", clsid=") GUIDFMT, GUIDPARM(clsidFlt)); + strFlt += tstr_printf(TEXT(", état=%") A2t, + EnumToString(eState, "Arrêt\0Pause\0Marche\0", "État inconnu")); + strState.insert(0, strFlt); // Insertion au début (pour inverser l'ordre) + } + + strState.insert(0, + tstr_printf( + TEXT("%") A2t TEXT("\n\n** Liste des filtres utilisés :"), + EnumToString(state, + "Le graphe est à l'arrêt\0" + "Le graphe est en pause\0" + "Le graphe est en marche\0", + "État du graphe inconnu"))); + MessageBox(hMainWnd, strState.c_str(), TEXT("État du graphe"), MB_ICONINFORMATION); +} +#endif + static void do_screenshot() { CComHeapPtr pDib; @@ -1444,6 +1547,13 @@ case IDM_CONFIG: do_config(hMainWnd); + + // Mise à jour du message sous MSN au cas où la configuration correspondante aurait changé + if (use_msn) + set_msn_msg(); + else + reset_msn_msg(); + 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) @@ -1704,18 +1814,10 @@ break; #ifdef _DEBUG - case IDM_GRAPH_STATE: { - myprintf(TEXT("Demande de l'état du graphe\n")); - OAFilterState state = graph_GetState(); + case IDM_GRAPH_STATE: + display_graph_state(); + break; - MessageBox(hMainWnd, - state==State_Stopped ? TEXT("Le graphe est à l'arrêt") : - state==State_Paused ? TEXT("Le graphe est en pause") : - state==State_Running ? TEXT("Le graphe est en marche") : - TEXT("État du graphe inconnu"), - TEXT("État du graphe"), MB_ICONINFORMATION); - break; } - case IDM_RUN_GRAPH: myprintf(TEXT("Mise en marche du graphe\n")); graph_Run(); @@ -2151,6 +2253,7 @@ case WM_APP_EPG_UPDATED: update_status_bar(); + update_msn_and_tip(); break; case WM_APP_PMT_UPDATED: @@ -2788,21 +2891,8 @@ niData.disable(); // Si on demandé la mise à jour de MSN, on retire le titre modifié - if (use_msn) { - // On cherche la fenêtre - HWND msnui = FindWindow(TEXT("MsnMsgrUIManager"), NULL); + reset_msn_msg(); - // Si, msnui == NULL, MSN ne fonctionne pas ou le fenêtre est masquée (donc, pas de mise à jour) - if (msnui != NULL) { - // Si on l'a trouvée, on efface la musique indiquée sur MSN - COPYDATASTRUCT msndata; - 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)hMainWnd, (LPARAM)&msndata); - } - } - return (int)msg.wParam; } Modifié: trunk/network.cpp =================================================================== --- trunk/network.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/network.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -122,6 +122,6 @@ // Return a non-addref'd pointer to pin n // needed by CBaseFilter CBasePin *CNetworkProvider::GetPin(int n) { -// myprintf(TEXT("GetPin %i\n"), n); +// myprintf(TEXT("CNetworkProvider::GetPin %i\n"), n); return (n==0) ? m_bidon : NULL; } Modifié: trunk/parse.cpp =================================================================== --- trunk/parse.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/parse.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -42,7 +42,7 @@ UINT16 pid = se().pid(); myprintf(TEXT("Service : 0x%04x, PMT PID : 0x%04x\n"), service_id, pid); - for (std::vector::iterator it = Canaux.begin(); it != Canaux.end(); it++) { + for (ITERATE_VECTOR(Canaux, Chaine, it)) { if (it->TSID==tsid && it->SID==service_id) { it->pmt_pid=(WORD)pid; } @@ -340,7 +340,7 @@ for(i = prev_size; i < Canaux.size(); i++) { Chaine & canal = Canaux[i]; - for(std::vector::iterator itt=chaineIDs.begin(); itt!=chaineIDs.end(); itt++) { + for (ITERATE_CONST_VECTOR(chaineIDs, ChaineIDs, itt)) { if (canal.ONID==itt->ONID && canal.TSID==itt->TSID && canal.SID==itt->SID) canal.numeroChaine = canal.numero_nit = itt->numero_nit; } Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/res.rc 2009-02-27 14:52:40 UTC (rev 174) @@ -148,21 +148,21 @@ BEGIN GROUPBOX "Configuration matérielle",IDC_STATIC,7,7,276,68 LTEXT "Tuner TNT",IDC_STATIC,14,20,55,12,SS_CENTERIMAGE - COMBOBOX IDC_COMBO_TUNER,76,20,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_TUNER,76,20,200,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Récepteur TNT",IDC_STATIC,14,36,55,12,SS_CENTERIMAGE - COMBOBOX IDC_COMBO_RECEIVER,76,36,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_RECEIVER,76,36,200,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP RTEXT "Correction de fréquence du tuner (kHz) :",IDC_STATIC,76,57,156,8 EDITTEXT IDC_TUNER_OFFSET,240,54,36,14,ES_CENTER | ES_AUTOHSCROLL CONTROL "",IDC_TUNER_OFFSET_UPDOWN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,265,54,10,14 GROUPBOX "Codecs utilisés",IDC_STATIC,7,86,276,84 LTEXT "Codec MPEG2",IDC_STATIC,14,100,55,12,SS_CENTERIMAGE - COMBOBOX IDC_COMBO_MPEG2,76,100,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_MPEG2,76,100,200,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Codec H264",IDC_COMBO_H264_S,14,116,55,12,SS_CENTERIMAGE - COMBOBOX IDC_COMBO_H264,76,116,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_H264,76,116,200,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Codec Audio",IDC_STATIC,14,132,55,12,SS_CENTERIMAGE - COMBOBOX IDC_COMBO_AUDIO,76,132,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_AUDIO,76,132,200,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Codec AC3",IDC_STATIC,14,148,55,12,SS_CENTERIMAGE - COMBOBOX IDC_COMBO_AC3,76,148,200,100,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_AC3,76,148,200,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "OK",IDOK,88,193,54,14 PUSHBUTTON "Annuler",IDCANCEL,148,193,54,14 END @@ -247,7 +247,7 @@ LTEXT "Fréquence",IDC_STATIC,48,28,35,8 LTEXT "Groupe",IDC_STATIC,104,28,24,8 LTEXT "Nom de la chaîne",IDC_STATIC,154,28,58,8 - LTEXT "Mpeg",IDC_STATIC,253,28,18,8 + LTEXT "Norme",IDC_STATIC,253,28,18,8 LISTBOX IDC_CHANNEL_LIST,7,36,276,128,LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP LTEXT "",IDC_SCAN_INFO,7,167,119,8 LTEXT "Progression de la recherche :",IDC_STATIC,7,180,99,10 @@ -266,7 +266,7 @@ 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 + PUSHBUTTON "Réinitialiser",IDC_RESET_EPG,446,289,54,14 DEFPUSHBUTTON "Fermer",IDOK,508,289,54,14 END Modifié: trunk/resource.h =================================================================== --- trunk/resource.h 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/resource.h 2009-02-27 14:52:40 UTC (rev 174) @@ -38,7 +38,7 @@ #define IDC_TUNER_OFFSET 1011 #define IDC_TUNER_OFFSET_UPDOWN 1012 #define IDC_LIST_EPG 1013 -#define IDC_UPDATE 1014 +#define IDC_RESET_EPG 1014 #define IDC_SIGNAL_PRESENT 1015 #define IDC_SIGNAL_LOCK 1016 #define IDC_SIGNAL_QUALITY 1017 Modifié: trunk/search.h =================================================================== --- trunk/search.h 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/search.h 2009-02-27 14:52:40 UTC (rev 174) @@ -90,38 +90,36 @@ }; /** - * Classe d'assistance au remplissage d'une liste déroulante + * Classe d'assistance au remplissage d'un tableau de chaînes de caractères * avec une liste de codecs ayant des caractéristiques données. */ -class CSearchByType_FillCombo : public CSearchByType +class CSearchByType_FillVector : public CSearchByType { - HWND hItem; + vector & vStrFiltres; public: /** - * Constructeur : prépare l'énumération pour le remplissage d'une - * liste déroulante avec une liste de codecs ayant des caractéristiques - * données. + * Constructeur : prépare l'énumération pour le remplissage d'un + * vecteur de chaînes de caractères avec une liste de codecs ayant des + * caractéristiques données. * \param[in] type CLSID pour le type * \param[in] subtype CLSID pour le sous-type * \param[in] bExactMatch true si correspondance exacte requise - * \param[in] hItm HANDLE de la liste déroulante à remplir. + * \param[in] vStrFlt tableau de chaînes de caractères à remplir. */ - CSearchByType_FillCombo(GUID type, GUID subtype, bool bExactMatch, HWND hItm) : + CSearchByType_FillVector(GUID type, GUID subtype, bool bExactMatch, vector & vStrFlt) : CSearchByType(type, subtype, bExactMatch), - hItem(hItm) - { - SendMessage(hItem, CB_ADDSTRING, 0, (LPARAM)TEXT("Aucun")); - } + vStrFiltres(vStrFlt) + {} /** - * Implémentation de méthode virtuelle appelée pour chaque codecs trouvé. + * Implémentation de méthode virtuelle appelée pour chaque codec trouvé. * \param[in] pMoniker "Moniker" vers ce filtre * \param[in] pszName nom du filtre * \return \p S_OK car tous les filtres doivent être énumérés */ virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCTSTR pszName) { - SendMessage(hItem, CB_ADDSTRING, 0, (LPARAM)pszName); + vStrFiltres.push_back(tstring(pszName)); return S_OK; } }; @@ -228,22 +226,22 @@ }; /** - * Classe d'assistance au remplissage d'une liste déroulante + * Classe d'assistance au remplissage d'un tableau de chaînes de caractères * avec une liste de filtres disponibles. */ -class CSearchByCategory_FillCombo : public CSearchByCategory +class CSearchByCategory_FillVector : public CSearchByCategory { - HWND hItem; + vector & vStrFiltres; public: /** * Constructeur : prépare l'énumération pour le remplissage d'une * liste déroulante avec une liste de filtres dans une catégorie donnée. * \param[in] clsid CLSID pour la catégorie - * \param[in] hItm HANDLE de la liste déroulante à remplir. + * \param[in] vStrFlt tableau de chaînes de caractères à remplir. */ - CSearchByCategory_FillCombo(CLSID clsid, HWND hItm) : + CSearchByCategory_FillVector(CLSID clsid, vector & vStrFlt) : CSearchByCategory(clsid), - hItem(hItm) + vStrFiltres(vStrFlt) {} /** @@ -255,8 +253,8 @@ virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCTSTR pszName) { if (filtre_compat(pCurFltr)!=compat_None) { - myprintf(TEXT("CSearchByCategory_FillCombo : %s\n"), pszName); - SendMessage(hItem, CB_ADDSTRING, 0, (LPARAM)pszName); + myprintf(TEXT("CSearchByCategory_FillVector : %s\n"), pszName); + vStrFiltres.push_back(tstring(pszName)); } return S_OK; } Modifié: trunk/settings.cpp =================================================================== --- trunk/settings.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/settings.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -238,6 +238,11 @@ #define CHAN_COL_NAME 4 ///< Colonne indiquant le nom de la chaîne #define CHAN_COL_STATE 5 ///< Colonne indiquant l'état de la chaîne #define CHAN_COL_MPEG 6 ///< Colonne indiquant le type de codage vidéo de diffusion (MPEG2, MPEG4 pour le moment) +#define CHAN_COL_TSID 7 ///< Colonne indiquant le TSID (Transport Stream ID) de la chaîne +#define CHAN_COL_ONID 8 ///< Colonne indiquant le ONID (Original Network ID) de la chaîne +#define CHAN_COL_SID 9 ///< Colonne indiquant le SID (Service ID) de la chaîne +#define CHAN_COL_VIDPID 10 ///< Colonne indiquant le PID vidéo de la chaîne +#define CHAN_COL_PMTPID 11 ///< Colonne indiquant le PID PMT de la chaîne /** * Définit l'état de la chaîne dans la liste @@ -293,24 +298,54 @@ item.iSubItem = CHAN_COL_CANAL; _stprintf_s(buffer, _countof(buffer), TEXT("%u"), canal.canal_no); ListView_SetItem(hListItem, &item); + // Fréquence de la chaîne item.iSubItem = CHAN_COL_FREQ; _stprintf_s(buffer, _countof(buffer), TEXT("%03u,%03u"), canal.khz/1000, canal.khz%1000); ListView_SetItem(hListItem, &item); - // Groute du multiplex de diffusion + + // Groupe du multiplex de diffusion item.iSubItem = CHAN_COL_GROUP; strcpy_T(buffer, canal.groupe); ListView_SetItem(hListItem, &item); + // Nom de la chaîne item.iSubItem = CHAN_COL_NAME; strcpy_T(buffer, canal.nom); ListView_SetItem(hListItem, &item); + // État de la chaîne (préféré, inactive, ...) State2LV(hListItem, iItem, canal.etat); + // Codec vidéo de diffusion item.iSubItem = CHAN_COL_MPEG; - _stprintf_s(buffer, _countof(buffer), TEXT("%c"), canal.norme()); + _stprintf_s(buffer, _countof(buffer), TEXT("%s"), canal.norme()); ListView_SetItem(hListItem, &item); + + // TSID + item.iSubItem = CHAN_COL_TSID; + _stprintf_s(buffer, _countof(buffer), TEXT("%u"), canal.TSID); + ListView_SetItem(hListItem, &item); + + // ONID + item.iSubItem = CHAN_COL_ONID; + _stprintf_s(buffer, _countof(buffer), TEXT("%u"), canal.ONID); + ListView_SetItem(hListItem, &item); + + // SID + item.iSubItem = CHAN_COL_SID; + _stprintf_s(buffer, _countof(buffer), TEXT("%u"), canal.SID); + ListView_SetItem(hListItem, &item); + + // PID vidéo + item.iSubItem = CHAN_COL_VIDPID; + _stprintf_s(buffer, _countof(buffer), TEXT("%u"), canal.pcr_pid); + ListView_SetItem(hListItem, &item); + + // PID PMT + item.iSubItem = CHAN_COL_PMTPID; + _stprintf_s(buffer, _countof(buffer), TEXT("%u"), canal.pmt_pid); + ListView_SetItem(hListItem, &item); } /** @@ -374,8 +409,13 @@ switch (iCol) { - case CHAN_COL_NO: { // N° + case CHAN_COL_NO: // N° case CHAN_COL_CANAL: // Canal + case CHAN_COL_TSID: + case CHAN_COL_ONID: + case CHAN_COL_SID: + case CHAN_COL_VIDPID: + case CHAN_COL_PMTPID: { int no1 =_tstoi(buf1); int no2 =_tstoi(buf2); @@ -805,13 +845,18 @@ { // Nom et largeur des différentes colonnes static const struct Tab_cols t_cols[] = { - {TEXT("N°"), 30}, - {TEXT("C."), 30}, - {TEXT("MHz"), 55}, - {TEXT("Groupe"), 60}, - {TEXT("Nom de la chaîne"), 120}, - {TEXT("État"), 60}, - {TEXT("Mp"), 30}, + {TEXT("N°"), 28}, // CHAN_COL_NO + {TEXT("C."), 28}, // CHAN_COL_CANAL + {TEXT("MHz"), 54}, // CHAN_COL_FREQ + {TEXT("Groupe"), 60}, // CHAN_COL_GROUP + {TEXT("Nom de la chaîne"), 120}, // CHAN_COL_NAME + {TEXT("État"), 60}, // CHAN_COL_STATE + {TEXT("Norme"), 48}, // CHAN_COL_MPEG + {TEXT("TsId"), 40}, // CHAN_COL_TSID + {TEXT("OnId"), 40}, // CHAN_COL_ONID + {TEXT("SId"), 40}, // CHAN_COL_SID + {TEXT("vPId"), 40}, // CHAN_COL_VIDPID + {TEXT("pPId"), 40}, // CHAN_COL_PMTPID {NULL, 0} // Terminateur }; @@ -1086,6 +1131,35 @@ * @{ */ /** + * Transfert d'une liste de filtres placée dans une table de chaînes de caractères + * vers une liste déroulante. La liste est préalablement triée, et un item "Aucun" + * est ajouté au début de la liste déroulante, et l'élément dont le nom est donné + * en paramètre est sélectionné. + * + * \param[in] vStrFiltres table contenant les noms de filtres + * \param[in] hItm handle de la liste déroulante recevant les noms de filtres + * \param[in] nom nom de l'élément à sélectionner + * \return la position de la sélection dans la liste déroulante + **/ +static LRESULT vectorstr_to_combo(vector & vStrFiltres, HWND hItm, LPCTSTR nom) +{ + // Tri de la table + std::sort(vStrFiltres.begin(), vStrFiltres.end()); + + // Ajout de l'item "Aucun" en début de liste + SendMessage(hItm, CB_ADDSTRING, 0, reinterpret_cast(TEXT("Aucun"))); + + // Ajout des items triés, juste derrière + for (ITERATE_CONST_VECTOR(vStrFiltres, tstring, it)) + SendMessage(hItm, CB_ADDSTRING, 0, reinterpret_cast(it->c_str())); + + // Sélection de l'item "nom" + if (IsNullCodec(nom)) + return SendMessage(hItm, CB_SETCURSEL, 0, 0); + return SendMessage(hItm, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)nom); +} + +/** * Remplit la liste déroulante contenant les tuners * * \param[in] hItm handle de la liste déroulante dans la boite de dialogue @@ -1096,8 +1170,11 @@ **/ static LRESULT remplit_combo_tuner(HWND hItm, GUID guid, LPCTSTR nom) { - CSearchByCategory_FillCombo(guid, hItm).Do(); - return SendMessage(hItm, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)nom); + vector vStrFiltres; + + CSearchByCategory_FillVector(guid, vStrFiltres).Do(); + + return vectorstr_to_combo(vStrFiltres, hItm, nom); } /** @@ -1112,10 +1189,11 @@ **/ static LRESULT remplit_combo_filtre(HWND hItm, GUID type, GUID subtype, LPCTSTR nom) { - CSearchByType_FillCombo(type, subtype, exact_match, hItm).Do(); - if (IsNullCodec(nom)) - return SendMessage(hItm, CB_SETCURSEL, 0, 0); - return SendMessage(hItm, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)nom); + vector vStrFiltres; + + CSearchByType_FillVector(type, subtype, exact_match, vStrFiltres).Do(); + + return vectorstr_to_combo(vStrFiltres, hItm, nom); } /** @@ -1442,15 +1520,16 @@ const Chaine & canal = Canaux[last_num]; if (canal.nom[0]) { - CHAR norme = canal.norme(); - TCHAR strnum[4] = TEXT("-"); // afficher '-' si zéro + LPCTSTR norme = canal.norme(); + TCHAR strnum[4] = TEXT("-"); // afficher '-' si zéro + LPCSTR groupe = *canal.groupe ? canal.groupe : ""; if (canal.numeroChaine > 0) _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"), + TEXT("%s\t%u\t%s\t%") A2t TEXT("\t%") A2t TEXT("\t%s"), strnum, canal.canal_no, szFreq, - *canal.groupe ? canal.groupe : "", canal.nom, norme); + groupe, canal.nom, norme); AddLineToList(hListItem, szTemp); } } Modifié: trunk/utils.cpp =================================================================== --- trunk/utils.cpp 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/utils.cpp 2009-02-27 14:52:40 UTC (rev 174) @@ -127,6 +127,20 @@ } /** + * Génération d'une chaîne formatée (format \p printf) avec résultat dans une chaîne \p tstring + **/ +tstring tstr_printf(LPCTSTR pszFmt, ...) +{ + TCHAR szBuffer[1024]; + + va_list args; + va_start(args, pszFmt); + _vstprintf_s(szBuffer, pszFmt, args); + va_end(args); + return tstring(szBuffer); +} + +/** * Change le style de la liste * * \param[in] hwndLV handle de la liste à modifier @@ -288,18 +302,34 @@ /** * Conversion d'une valeur d'un type énuméré vers une chaîne de caractères * sélectionnée dans une chaîne fournissant une suite de résultats possibles + * + * \param[in] nVal Valeur à associer + * \param[in] pszList Chaîne contenant une suite d'items séparés par des zéros binaires ; + * un item débutant par \p 0x01 ("un" binaire) est remplacé par l'item par + * défaut ; un item vide (donc deux zéros successifs) DOIT terminer. + * \param[in] pszDefault Valeur par défaut + * \retval Une copie de l'item de rang \p nVal (base 0), ou bien \p pszDefault + * si \p nVal excède le nombre d'items ou si l'item débute par \p 0x01. + * \note \p pszList doit être une chaîne constante, ou bien au moins statique. + * \note Cette fonction permet de ne pas avoir de tableau externe pour effectuer la conversion. + * \note Aucun item ne peut être vide, puisqu'il serait alors d'office terminateur. + * \note Étant donnée la longueur possible de la chaîne \p pszList et le fait que la + * fonction est plutôt d'usage debugging, on n'utilise pas de caractères \p TCHAR. **/ -LPCSTR EnumToString(int nVal, LPCSTR pszList) +LPCSTR EnumToString(int nVal, LPCSTR pszList, LPCSTR pszDefault) { - if (nVal>=0) { + if (pszList && nVal>=0) { while (*pszList) { // Tant qu'on n'a pas une chaîne vide - if (nVal==0) + if (nVal==0) { + if (pszList[0]==1) + break; return pszList; + } pszList += strlen(pszList)+1; nVal--; } } - return "??"; + return pszDefault; } /** Modifié: trunk/utils.h =================================================================== --- trunk/utils.h 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/utils.h 2009-02-27 14:52:40 UTC (rev 174) @@ -433,6 +433,11 @@ typedef std::string tstring; //!< Alias "TCHAR" pour \p string ou \p wstring #endif +/** + * Génération d'une chaîne formatée (format \p printf) avec résultat dans une chaîne \p tstring + **/ +tstring tstr_printf(LPCTSTR pszFmt, ...); + // ---------------------------------------------------------------------------- /** @@ -604,17 +609,18 @@ * * \param[in] nVal Valeur à associer * \param[in] pszList Chaîne contenant une suite d'items séparés par des zéros binaires ; - * Un item vide (donc deux zéros successifs) DOIT terminer. - * \retval Une copie de l'item de rang \p nVal (base 0), ou bien "??" - * si \p nVal excède le nombre d'items. + * un item débutant par \p 0x01 ("un" binaire) est remplacé par l'item par + * défaut ; un item vide (donc deux zéros successifs) DOIT terminer. + * \param[in] pszDefault Valeur par défaut + * \retval Une copie de l'item de rang \p nVal (base 0), ou bien \p pszDefault + * si \p nVal excède le nombre d'items ou si l'item débute par \p 0x01. * \note \p pszList doit être une chaîne constante, ou bien au moins statique. - * \note Cette fonction est principalement destinée aux messages de debugging rapides, - * puisqu'elle permet de ne pas avoir de tableau externe pour effectuer la conversion. + * \note Cette fonction permet de ne pas avoir de tableau externe pour effectuer la conversion. * \note Aucun item ne peut être vide, puisqu'il serait alors d'office terminateur. * \note Étant donnée la longueur possible de la chaîne \p pszList et le fait que la - * fonction est plutôt d'usage debugging, on n'utilise pas de caractères \ TCHAR. + * fonction est plutôt d'usage debugging, on n'utilise pas de caractères \p TCHAR. **/ -LPCSTR EnumToString(int nVal, LPCSTR pszList); +LPCSTR EnumToString(int nVal, LPCSTR pszList, LPCSTR pszDefault="??"); /** * Recherche le premier fichier passé en paramètre, et ceci, de manière récursive @@ -678,12 +684,40 @@ **/ int ConvertChar2UTF8(UINT32 aconvertir, LPSTR & convertis); +// ---------------------------------------------------------------------------- + /** * Macro d'assistance à l'énumération d'interface + * \param[in] parent Nom de l'objet dont les éléments doivent être énumérés + * \param[in] type Type des objets énumérés + * \param[in] name Nom de l'objet recevant les instances d'objets énumérés **/ #define ENUM_ITF(parent, type, name) \ CComPtr name; \ - parent->Next(1, &name, NULL)==S_OK; \ + (parent)->Next(1, &name, NULL)==S_OK; \ name.Release() +/** + * Macro d'assistance à l'énumération d'éléments de vecteurs + * \param[in] parent Nom du vecteur dont les éléments doivent être énumérés + * \param[in] type Type des éléments énumérés + * \param[in] name Nom du pointeur sur les éléments énumérés + **/ +#define ITERATE_VECTOR(parent, type, name) \ + std::vector::iterator name = (parent).begin(); \ + name != (parent).end(); \ + name++ + +/** + * Macro d'assistance à l'énumération d'éléments de vecteurs constants + * \param[in] parent Nom du vecteur dont les éléments doivent être énumérés + * \param[in] type Type des éléments énumérés + * \param[in] name Nom du pointeur sur les éléments énumérés + **/ +#define ITERATE_CONST_VECTOR(parent, type, name) \ + std::vector::const_iterator name = (parent).begin(); \ + name != (parent).end(); \ + name++ + + // ---------------------------------------------------------------------------- Modifié: trunk/version =================================================================== --- trunk/version 2009-02-21 22:44:54 UTC (rev 173) +++ trunk/version 2009-02-27 14:52:40 UTC (rev 174) @@ -1 +1 @@ -0,4 +0,5 From pouchintv-dev at baysse.fr Fri Feb 27 16:47:06 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Fri, 27 Feb 2009 16:47:06 +0100 Subject: [Pouchintv-dev] =?iso-8859-1?q?Proposition_=3A_num=E9rotation_des?= =?iso-8859-1?q?_versions=2E?= References: <20090221224455.47D6C5F436@mail.baysse.fr> <000c01c997f6$3fa92b10$4001a8c0@bunny> Message-ID: ----- Original Message ----- From: "Liste utilisée par les développeurs" To: "Liste utilisée par les développeurs" Sent: Thursday, February 26, 2009 10:40 AM Subject: Re: [Pouchintv-dev]Proposition : numérotation des versions. > Bonjour, > > C'est parfait, > > ef15c Bonjour, Personne d'autre n'ayant répondu à cette question au bout de 5 jours, je me suis donc permis de présumer que tout le monde était d'accord, et je viens de livrer une mise à jour dans le SVN qui fait passer le numéro de version de 0.4 à 0.5. J'ai également publié, dans le forum, un nouvel installateur de cette version, toujours considérée comme expérimentale. http://pouchintv.baysse.fr/forum/viewtopic.php?f=7&t=473 Gingko