From pouchintv-dev at baysse.fr Sat Nov 1 23:28:46 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sat, 1 Nov 2008 23:28:46 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] lolo_32 | r134 - trunk Message-ID: <20081101222846.5D2895F5ED@mail.baysse.fr> Author: lolo_32 Date: 2008-11-01 23:28:46 +0100 (sam, 01 nov 2008) New Revision: 134 Modified: trunk/chanutils.cpp trunk/chanutils.h trunk/xml.cpp Log: xml.cpp * Correction d'un boggue entraînant le retour d'une chaine de caractères de taille suppéieure à la mémoire allouée dans certains cas. chanutils.cpp, chanutils.h * Correction d'un boggue dans la gestion des langues des pistes, car la zone mémoire devant contenir le nom de la langue n'était pas effacé. Modifié: trunk/chanutils.cpp =================================================================== --- trunk/chanutils.cpp 2008-10-26 19:43:31 UTC (rev 133) +++ trunk/chanutils.cpp 2008-11-01 22:28:46 UTC (rev 134) @@ -37,6 +37,11 @@ #include "chanutils.h" + +une_piste::une_piste(const une_piste &piste) { + pid = piste.pid; type=piste.type; + strcpy_s(lang, _countof(lang), piste.lang); +} bool liste_pistes::operator == (const liste_pistes & lp) const { if (nbr!=lp.nbr) Modifié: trunk/chanutils.h =================================================================== --- trunk/chanutils.h 2008-10-26 19:43:31 UTC (rev 133) +++ trunk/chanutils.h 2008-11-01 22:28:46 UTC (rev 134) @@ -47,6 +47,10 @@ UINT8 type; // si son : 0 = normal, 1 = AC3; réservé si autres char lang[8]; + // Efface le tableau de caractère, car pose des problèmes des fois si pas effacé + une_piste() : pid(0), type(0) {ZeroMemory(lang, sizeof(lang)); }; + une_piste(const une_piste &piste); + bool operator == (const une_piste & up) const {return pid==up.pid && type==up.type/* && strcmp(lang, up.lang)==0*/;} // (strcmp pas nécessaire pour le moment) Modifié: trunk/xml.cpp =================================================================== --- trunk/xml.cpp 2008-10-26 19:43:31 UTC (rev 133) +++ trunk/xml.cpp 2008-11-01 22:28:46 UTC (rev 134) @@ -154,11 +154,12 @@ void CXMLNode::getStr(const wchar_t * nom, char * str, size_t size) { - wchar_t buffer[64]; - ZeroMemory(buffer, sizeof(buffer)); + wchar_t *buffer = new wchar_t[size]; + ZeroMemory(buffer, size); - getStr(nom, buffer, _countof(buffer)); + getStr(nom, buffer, size); WideCharToMultiByte(CP_ACP, 0, buffer, -1, str, size, NULL, NULL); + delete buffer; } /** From pouchintv-dev at baysse.fr Sat Nov 8 00:19:58 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sat, 8 Nov 2008 00:19:58 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] lolo_32 | r135 - in trunk/Icones: . Locales Message-ID: <20081107231958.8CBCD5F329@mail.baysse.fr> Author: lolo_32 Date: 2008-11-08 00:19:57 +0100 (sam, 08 nov 2008) New Revision: 135 Added: trunk/Icones/ARTE HD.bmp trunk/Icones/France 2 HD.bmp trunk/Icones/M6HD.bmp trunk/Icones/TF1 HD.bmp Modified: trunk/Icones/Direct 8.bmp trunk/Icones/Locales/TV RENNES 35.bmp Log: Ajout des icônes pour les chaines HD Ajouté: trunk/Icones/ARTE HD.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/ARTE HD.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Modifié: trunk/Icones/Direct 8.bmp =================================================================== (les fichiers binaires diffèrent) Ajouté: trunk/Icones/France 2 HD.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/France 2 HD.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Property changes on: trunk/Icones/Locales/TV RENNES 35.bmp ___________________________________________________________________ Nom : svn:mime-type - application/octet-stream + image/x-ms-bmp Ajouté: trunk/Icones/M6HD.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/M6HD.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Ajouté: trunk/Icones/TF1 HD.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/TF1 HD.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp From pouchintv-dev at baysse.fr Sun Nov 9 18:11:45 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sun, 9 Nov 2008 18:11:45 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r136 - trunk Message-ID: <20081109171145.3A06C5F331@mail.baysse.fr> Author: gingko Date: 2008-11-09 18:11:44 +0100 (dim, 09 nov 2008) New Revision: 136 Modified: trunk/LCD.cpp trunk/Pouchin TV.vcproj trunk/base.cpp trunk/base.h trunk/channels.cpp trunk/graph.cpp trunk/main.cpp trunk/recprog.cpp trunk/res.rc trunk/search.cpp trunk/search.h trunk/settings.cpp Log: Amélioration du système d'affichage des erreurs, et en particulier de celles générées dans le graphe : la fonction "erreur" est maintenant séparée en deux fonctions, l'une gardant l'ancien nom "erreur", mais se contentant dorénavant d'accumuler les messages dans un tampon, et l'autre nommée "affiche_erreurs", qui affiche tous les messages du tampon en une fois, plus éventuellement les siens propres. Ceci évite la cascade de messages d'alerte qui pouvait auparavant se succéder à chaque sortie de fonction. Au passage, les codes d'erreurs numériques sont maintenant décodés en clair (grâce à une fonction native de DirectShow). Les messages d'erreurs sont aussi, de manière générale, remplacés par des messages de style plus "professionnel", et certains nouveaux tests d'erreurs avec messages ont été ajoutés. Dans le graphe, la fonction "render_mpeg2" est renommée en "render_psi", ce qui correspond davantage à son rôle d'extraction des tables PSI. Dans le dialogue des options (ressources), certains items sont remis en ordre. Modifié: trunk/LCD.cpp =================================================================== --- trunk/LCD.cpp 2008-11-07 23:19:57 UTC (rev 135) +++ trunk/LCD.cpp 2008-11-09 17:11:44 UTC (rev 136) @@ -108,11 +108,11 @@ ret = lgLcdInit(); if (ret != ERROR_SUCCESS) { - // Erreur d'initialisation de la librairie + // Erreur d'initialisation de la bibliothèque return false; } - // Initialisation de la librairie OK! + // Initialisation de la bibliothèque OK ! ZeroMemory(&this->m_connectContext, sizeof(this->m_connectContext)); // Nom de l'affichage dans le LCD Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2008-11-07 23:19:57 UTC (rev 135) +++ trunk/Pouchin TV.vcproj 2008-11-09 17:11:44 UTC (rev 136) @@ -65,7 +65,7 @@ /> + + AddFilter(pFilter, nom); + if (FAILED(hr)) { - pFilter->Release(); // nécessaire ?? - return hr; + pFilter->Release(); + erreur(L"Le filtre \"%s\" n'a pas pu être ajouté au graphe", hr, nom); } return hr; @@ -207,14 +209,14 @@ { HRESULT hr = pNetworkTuner->QueryInterface(&pBDAControl); if (FAILED(hr)) { - erreur(L"IBDA_DeviceControl", hr); + erreur(L"L'interface IBDA_DeviceControl n'a pas été trouvée", hr); return hr; } IBDA_Topology * pTop; hr = pNetworkTuner->QueryInterface(&pTop); if (FAILED(hr)) { - myprintf(L"IBDA_Topology : %08X\n", hr); + erreur(L"L'interface IBDA_Topology n'a pas été trouvée", hr); return hr; } @@ -262,7 +264,7 @@ IBDA_Topology * pTop; HRESULT hr = pNetworkTuner->QueryInterface(&pTop); if (FAILED(hr)) { - myprintf(L"IBDA_Topology : %08X\n", hr); + erreur(L"L'interface IBDA_Topology n'a pas été trouvée", hr); return hr; } @@ -340,20 +342,18 @@ HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"video", &pVideoPin); if (FAILED(hr)) { - erreur(L"pas créé pin video", hr); + erreur(L"La broche vidéo MPEG2 n'a pas pu être créée", hr); return hr; } // le décodeur vidéo - pVideoCodec = get_filter(MEDIATYPE_Video, MEDIASUBTYPE_MPEG2_VIDEO, filtreMPEG2); + hr = get_filter(MEDIATYPE_Video, MEDIASUBTYPE_MPEG2_VIDEO, filtreMPEG2, pVideoCodec); + if (SUCCEEDED(hr)) { + myprintf(L"Ajout video MPEG2\n"); - if (pVideoCodec != NULL) { - - myprintf(L"ajout video\n"); - hr = pGraph->AddFilter(pVideoCodec, L"Codec vidéo"); if (FAILED(hr)) { - erreur(L"Codec vidéo non inséré dans le graph", hr); + erreur(L"Le codec vidéo MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreMPEG2); return hr; } @@ -361,20 +361,18 @@ hr = cherche_pin(pVideoCodec, PINDIR_INPUT, pPinEntree); if (SUCCEEDED(hr) && pPinEntree!=NULL) { - hr = pGraph->ConnectDirect(pVideoPin, pPinEntree, NULL); - pPinEntree->Release(); + hr = pGraph->ConnectDirect(pVideoPin, pPinEntree, NULL); + pPinEntree->Release(); } if (FAILED(hr)) { - erreur(L"Impossible de connecter le demux au codec vidéo", hr); + erreur(L"Impossible de connecter le démultiplexeur au codec vidéo MPEG2 \"%s\"", hr, filtreMPEG2); return hr; } - - } else { hr = pGraph->RenderEx(pVideoPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); if (FAILED(hr)) { - erreur(L"pas trouvé de codec vidéo", hr); + erreur(L"Pas de rendu possible depuis la broche vidéo MPEG2", hr); return hr; } } @@ -395,31 +393,29 @@ // crée le VMR hr = create_and_add_filter(MyCLSID_VideoMixingRenderer, L"Mon VMR", pVMR); - - if (FAILED(hr) || pVMR == NULL) { - erreur(L"VMR non inséré", hr); + if (FAILED(hr)) return hr; - } - { MyIVMRFilterConfig * pVMRConfig; hr = pVMR->QueryInterface(&pVMRConfig); if (FAILED(hr)) { - erreur(L"VMR config non dispo", hr); + erreur(L"L'interface de configuration VMR n'est pas disponible", hr); return hr; } #if USE_VMR9 - pVMRConfig->SetRenderingMode(MyVMRMode_Windowless); + hr = pVMRConfig->SetRenderingMode(MyVMRMode_Windowless); #else - pVMRConfig->SetRenderingMode(MyVMRMode_Renderless); + hr = pVMRConfig->SetRenderingMode(MyVMRMode_Renderless); - if (use_vmr_deinterlace) - pVMRConfig->SetNumberOfStreams(1); + if (SUCCEEDED(hr) && use_vmr_deinterlace) + hr = pVMRConfig->SetNumberOfStreams(1); #endif pVMRConfig->Release(); + if (FAILED(hr)) + return hr; } #if !USE_VMR9 // Modif R_One - à revérifier @@ -427,36 +423,43 @@ IVMRSurfaceAllocatorNotify * pNotify; hr = pVMR->QueryInterface(&pNotify); if (FAILED(hr)) { - erreur(L"VMR notify non dispo", hr); + erreur(L"L'interface IVMRSurfaceAllocatorNotify n'a pas été trouvée", hr); return hr; } IVMRSurfaceAllocator * pSurfAlloc; - CoCreateInstance(CLSID_AllocPresenter, NULL, + hr = CoCreateInstance(CLSID_AllocPresenter, NULL, CLSCTX_INPROC_SERVER, IID_IVMRSurfaceAllocator, (LPVOID*)&pSurfAlloc); + if (FAILED(hr)) { + erreur(L"L'interface IVMRSurfaceAllocator n'a pas été trouvée", hr); + return hr; + } + IVMRImagePresenterConfig * pPresConf = NULL; + hr = pSurfAlloc->QueryInterface(&pPresConf); - myprintf(L"IVMRImagePresenterConfig 0x%08x\n", pPresConf); + if (FAILED(hr)) { + erreur(L"L'interface IVMRImagePresenterConfig n'a pas été trouvée", hr); + return hr; + } + if (is_vista) { hr = pPresConf->SetRenderingPrefs(RenderPrefs_AllowOffscreen); } else { hr = pPresConf->SetRenderingPrefs(RenderPrefs_ForceOverlays | RenderPrefs_DoNotRenderColorKeyAndBorder); } + pPresConf->Release(); if (FAILED(hr)) { - erreur(L"VMR ImagePresenterConfig non dispo", hr); + erreur(L"Échec de SetRenderingPrefs", hr); return hr; } - pPresConf->Release(); - pNotify->AdviseSurfaceAllocator(0x118218, pSurfAlloc); - pSurfAlloc->AdviseNotify(pNotify); - } if (use_vmr_deinterlace) { @@ -464,69 +467,69 @@ MyIVMRMixerControl * pMixControl; hr = pVMR->QueryInterface(&pMixControl); + if (FAILED(hr)) { + erreur(L"L'interface IVMRMixerControl n'a pas été trouvée", hr); + return hr; + } + hr = pMixControl->SetMixingPrefs(MyMixingPrefs); + pMixControl->Release(); if (FAILED(hr)) { - erreur(L"Pas eu le VMRMixerControl :/", hr); - } else { + erreur(L"Échec de SetMixingPrefs", hr); + return hr; + } - pMixControl->SetMixingPrefs(MyMixingPrefs); + MyIVMRDeinterlaceControl * pDeint; + hr = pVMR->QueryInterface(&pDeint); + if (FAILED(hr)) { + erreur(L"L'interface IVMRDeinterlaceControl n'a pas été trouvée", hr); + return hr; + } - pMixControl->Release(); + DWORD num; + MyVMRVideoDesc desc; - MyIVMRDeinterlaceControl * pDeint; - hr = pVMR->QueryInterface(&pDeint); - - if (FAILED(hr)) { - erreur(L"Pas eu le DeinterlaceControl :/", hr); - } else { - - DWORD num; - - MyVMRVideoDesc desc; - desc.dwSize = sizeof(MyVMRVideoDesc); - desc.dwSampleWidth = 720; - desc.dwSampleHeight = 576; + desc.dwSize = sizeof(desc); + desc.dwSampleWidth = 720; + desc.dwSampleHeight = 576; #if USE_VMR9 - desc.SampleFormat = VMR9_SampleFieldInterleavedEvenFirst; - // desc.SampleFormat = VMR9_SampleFieldSingleEven; + desc.SampleFormat = VMR9_SampleFieldInterleavedEvenFirst; + // desc.SampleFormat = VMR9_SampleFieldSingleEven; #else // #if USE_VMR9 - desc.SingleFieldPerSample = TRUE; + desc.SingleFieldPerSample = TRUE; #endif // #if USE_VMR9 - // desc.dwFourCC =MAKEFOURCC('Y','V','1','2'); - desc.dwFourCC =MAKEFOURCC('Y','U','Y','2'); - desc.InputSampleFreq.dwNumerator = 25; - desc.InputSampleFreq.dwDenominator = 1; - desc.OutputFrameFreq.dwNumerator = 50; - desc.OutputFrameFreq.dwDenominator = 1; + // desc.dwFourCC =MAKEFOURCC('Y','V','1','2'); + desc.dwFourCC =MAKEFOURCC('Y','U','Y','2'); + desc.InputSampleFreq.dwNumerator = 25; + desc.InputSampleFreq.dwDenominator = 1; + desc.OutputFrameFreq.dwNumerator = 50; + desc.OutputFrameFreq.dwDenominator = 1; - hr = pDeint->GetNumberOfDeinterlaceModes(&desc, &num, NULL); + hr = pDeint->GetNumberOfDeinterlaceModes(&desc, &num, NULL); - if (FAILED(hr)) { - erreur(L"Nombre de modes de désentrelacement non trouvé", hr); - return hr; - } + if (FAILED(hr)) { + erreur(L"Nombre de modes de désentrelacement non trouvé", hr); + return hr; + } - myprintf(L"num : %i\n", num); + myprintf(L"num : %i\n", num); - GUID guid[1]; - num = 1; + GUID guid[1]; + num = 1; - hr = pDeint->GetNumberOfDeinterlaceModes(&desc, &num, guid); + hr = pDeint->GetNumberOfDeinterlaceModes(&desc, &num, guid); - if (FAILED(hr)) { - erreur(L"Impossible d'avoir le GUID du désentrelacement", hr); - return hr; - } + if (FAILED(hr)) { + erreur(L"Impossible d'avoir le GUID du désentrelacement", hr); + return hr; + } - hr = pDeint->SetDeinterlaceMode(0xFFFFFFFF, &guid[0]); + hr = pDeint->SetDeinterlaceMode(0xFFFFFFFF, &guid[0]); + pDeint->Release(); - if (FAILED(hr)) { - erreur(L"Impossible de mettre le mode de désentrelacement", hr); - return hr; - } - - pDeint->Release(); - } + if (FAILED(hr)) { + erreur(L"Impossible de mettre le mode de désentrelacement", hr); + return hr; } } #endif // #if !USE_VMR9 @@ -534,7 +537,7 @@ hr = pVMR->QueryInterface(&pVMRControl); if (FAILED(hr)) { - erreur(L"Pas de VMR control !", hr); + erreur(L"L'interface de contrôle VMR n'est pas disponible", hr); return hr; } @@ -549,26 +552,24 @@ hr = pVMR->QueryInterface(&pARC); if (FAILED(hr)) { - erreur(L"Pas de AspectRatioControl !", hr); + erreur(L"L'interface de contrôle du ratio d'aspect n'est pas disponible", hr); return hr; } pARC->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX); - pARC->Release(); } if (pVideoCodec != NULL) { - hr = connect_filters(pVideoCodec, pVMR); if (FAILED(hr)) { - erreur(L"Impossible de connecter le codec vidéo au VMR.\nC'est probablement l'overlay qui n'est pas disponible.\n\nVeuillez le libérer et relancer l'application", hr); - return hr; + // Ici, on affiche l'erreur mais on ne quitte pas (ça laisse la possibilité d'enregistrer) + affiche_erreurs(L"Impossible de connecter le codec vidéo au VMR.\nC'est probablement l'overlay qui n'est pas disponible.\n\nVeuillez le libérer et relancer l'application", hr); } } else { - erreur(L"pas trouvé de codec vidéo"); + erreur(L"Il n'y a pas de codec vidéo disponible", hr); return hr; } @@ -605,54 +606,51 @@ HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"son", &pSoundPin); if (FAILED(hr)) { - erreur(L"pas créé pin son", hr); + erreur(L"La broche audio MPEG2 n'a pas pu être créée", hr); return hr; } // add direct sound hr = create_and_add_filter(CLSID_DSoundRender, L"Direct sound", pDSound); - if (FAILED(hr) || pDSound == NULL) { - erreur(L"Direct sound pas ajouté", hr); + if (FAILED(hr)) return hr; - } // le décodeur audio - pAudioCodec = get_filter(MEDIATYPE_Audio, MEDIASUBTYPE_MPEG2_AUDIO, filtreAudio); + hr = get_filter(MEDIATYPE_Audio, MEDIASUBTYPE_MPEG2_AUDIO, filtreAudio, pAudioCodec); + if (SUCCEEDED(hr)) { - if (pAudioCodec != NULL) { - myprintf(L"ajout audio\n"); hr = pGraph->AddFilter(pAudioCodec, L"Codec audio"); if (FAILED(hr)) { - erreur(L"Codec audio non inséré dans le graph", hr); - return 1; + erreur(L"Le codec audio MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAudio); + return hr; } IPin * pPinEntree = NULL; hr = cherche_pin(pAudioCodec, PINDIR_INPUT, pPinEntree); if (SUCCEEDED(hr) && pPinEntree != NULL) { - hr = pGraph->ConnectDirect(pSoundPin, pPinEntree, NULL); - pPinEntree->Release(); + hr = pGraph->ConnectDirect(pSoundPin, pPinEntree, NULL); + pPinEntree->Release(); } if (FAILED(hr)) { - erreur(L"Impossible de connecter le demux au codec audio", hr); + erreur(L"Impossible de connecter le démultiplexeur au codec audio MPEG2 \"%s\"", hr, filtreAudio); return hr; } hr = connect_filters(pAudioCodec, pDSound); if (FAILED(hr)) { - erreur(L"connec Codec audio", hr); + erreur(L"Impossible de connecter le Codec audio MPEG2 \"%s\" au filtre de rendu DirectSound", hr, filtreAudio); return hr; } } else { hr = pGraph->RenderEx(pSoundPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); if (FAILED(hr)) { - erreur(L"pas render son", hr); + erreur(L"Pas de rendu possible depuis la broche audio MPEG2", hr); return hr; } } @@ -693,28 +691,25 @@ HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"ac3", &pAc3Pin); if (FAILED(hr)) { - erreur(L"pas créé pin ac3", hr); + erreur(L"La broche audio AC3 n'a pas pu être créée", hr); return hr; } // add direct sound hr = create_and_add_filter(CLSID_DSoundRender, L"Direct sound le retour", pDSoundAc3); - if (FAILED(hr) || pDSoundAc3 == NULL) { - erreur(L"Direct sound le retour not added", hr); + if (FAILED(hr)) return hr; - } // le décodeur ac3 - pAc3Codec = get_filter(MEDIATYPE_Audio, MEDIASUBTYPE_DOLBY_AC3, filtreAc3); + hr = get_filter(MEDIATYPE_Audio, MEDIASUBTYPE_DOLBY_AC3, filtreAc3, pAc3Codec); + if (SUCCEEDED(hr)) { - if (pAc3Codec != NULL) { - myprintf(L"ajout ac3\n"); hr = pGraph->AddFilter(pAc3Codec, L"Codec ac3"); if (FAILED(hr)) { - erreur(L"Codec AC3 non inséré dans le graph", hr); + erreur(L"Le codec audio AC3 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAc3); return hr; } @@ -722,25 +717,25 @@ hr = cherche_pin(pAc3Codec, PINDIR_INPUT, pPinEntree); if (SUCCEEDED(hr) && pPinEntree!=NULL) { - hr = pGraph->ConnectDirect(pAc3Pin, pPinEntree, NULL); - pPinEntree->Release(); + hr = pGraph->ConnectDirect(pAc3Pin, pPinEntree, NULL); + pPinEntree->Release(); } if (FAILED(hr)) { - erreur(L"Impossible de connecter le demux au codec AC3", hr); + erreur(L"Impossible de connecter le démultiplexeur au codec AC3 \"%s\"", hr, filtreAc3); return hr; } hr = connect_filters(pAc3Codec, pDSoundAc3); if (FAILED(hr)) { - erreur(L"connec Codec audio", hr); + erreur(L"Impossible de connecter le Codec audio AC3 \"%s\" au filtre de rendu DirectSound", hr, filtreAc3); return hr; } } else { hr = pGraph->RenderEx(pAc3Pin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); if (FAILED(hr)) { - erreur(L"pas render son", hr); + erreur(L"Pas de rendu possible depuis la broche audio AC3", hr); return hr; } } @@ -753,7 +748,7 @@ } -static HRESULT render_mpeg2(IMpeg2Demultiplexer * pMpeg2Demux) +static HRESULT render_psi(IMpeg2Demultiplexer * pMpeg2Demux) { IPin * pDataPin; @@ -771,7 +766,7 @@ HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"data", &pDataPin); if (FAILED(hr)) { - erreur(L"pas créé pin data", hr); + erreur(L"La broche PSI n'a pas pu être créée", hr); return hr; } @@ -780,17 +775,15 @@ IBaseFilter * pMpeg2Filter = NULL; hr = create_and_add_filter(__uuidof(Mpeg2Data), L"MPEG2 data", pMpeg2Filter); - if (FAILED(hr) || pMpeg2Filter == NULL) { - erreur(L"MPEG2 data pas inséré", hr); + if (FAILED(hr)) return hr; - } // query MPEG-2 Sections and Tables Filter hr = pMpeg2Filter->QueryInterface(&pMpeg2Data); if (FAILED(hr)) { - erreur(L"pas eu le mpeg2data", hr); + erreur(L"L'interface d'accès aux tables PSI n'a pas été trouvée", hr); return hr; } @@ -803,7 +796,7 @@ } if (FAILED(hr)) { - erreur(L"Impossible de connecter le demux au mpeg2data", hr); + erreur(L"Impossible de connecter le démultiplexeur au filtre PSI", hr); return hr; } @@ -833,7 +826,7 @@ HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"epg", &pEpgPin); if (FAILED(hr)) { - erreur(L"pas créé pin epg", hr); + erreur(L"La broche EPG n'a pas pu être créée", hr); return hr; } @@ -842,9 +835,13 @@ CLSID clsid = {5, 6, 7, 8, 9, 10, 11, 12, 13}; CEPGFilter * pEPGFilter = new CEPGFilter(clsid, &hr); + if (FAILED(hr)) { + erreur(L"Le filtre EPG n'a pas pu être créé", hr); + return hr; + } hr = pGraph->AddFilter(pEPGFilter, L"Mon filtre EPG"); if (FAILED(hr)) { - erreur(L"pas ajouté filtre EPG au graph", hr); + erreur(L"Le filtre EPG n'a pas pu être ajouté au graphe", hr); return hr; } @@ -852,7 +849,7 @@ hr = cherche_pin(pEPGFilter, PINDIR_INPUT, pPinEntree); if (FAILED(hr) || pEPGFilter == NULL) { - erreur(L"pas trouvé pin entrée", hr); + erreur(L"La broche d'entrée EPG n'a pas été trouvée", hr); return hr; } @@ -860,7 +857,7 @@ pPinEntree->Release(); if (FAILED(hr)) { - erreur(L"pas connecté pin entrée", hr); + erreur(L"La broche d'entrée EPG n'a pas pu être connectée", hr); return hr; } } @@ -896,7 +893,7 @@ HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"pmt", &pPmtPin); if (FAILED(hr)) { - erreur(L"pas créé pin pmt", hr); + erreur(L"La broche PMT n'a pas pu être créée", hr); return hr; } @@ -906,13 +903,13 @@ CPMTFilter * pPMTFilter = new CPMTFilter(clsid, &hr); if (FAILED(hr) || pPMTFilter == NULL) { - erreur(L"pas pu créer filtre PMT", hr); + erreur(L"Le filtre PMT n'a pas pu être créé", hr); return hr; } hr = pGraph->AddFilter(pPMTFilter, L"Mon filtre PMT"); if (FAILED(hr)) { - erreur(L"pas ajouté PMT filtre au graph", hr); + erreur(L"Le filtre PMT n'a pas pu être ajouté au graphe", hr); return hr; } @@ -921,7 +918,7 @@ hr = cherche_pin(pPMTFilter, PINDIR_INPUT, pPinEntree); if (FAILED(hr) || pPMTFilter == NULL) { - erreur(L"pas trouvé pin entrée", hr); + erreur(L"La broche d'entrée PMT n'a pas été trouvée", hr); return hr; } @@ -929,7 +926,7 @@ pPinEntree->Release(); if (FAILED(hr)) { - erreur(L"pas connecté pin entrée", hr); + erreur(L"La broche d'entrée PMT n'a pas pu être connectée", hr); return hr; } @@ -954,37 +951,37 @@ hr = pDemux->QueryInterface(&pMpeg2Demux); if (FAILED(hr)) { - erreur(L"Demux MPEG2 non valide !", hr); + erreur(L"L'interface du démultiplexeur n'a pas été trouvée", hr); return hr; } if (FAILED(hr = render_mp2v(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu du pin mp2v", hr); + erreur(L"Erreur lors du rendu de la broche vidéo MPEG2", hr); return hr; } if (FAILED(hr = render_son(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu du pin son", hr); + erreur(L"Erreur lors du rendu de la broche audio MPEG2", hr); return hr; } if (FAILED(hr = render_ac3(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu du pin ac3", hr); + erreur(L"Erreur lors du rendu de la broche audio AC3", hr); return hr; } - if (FAILED(hr = render_mpeg2(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu du pin mpeg2", hr); + if (FAILED(hr = render_psi(pMpeg2Demux))) { + erreur(L"Erreur lors du rendu de la broche PSI", hr); return hr; } if (FAILED(hr = render_epgfilter(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu du pin epg", hr); + erreur(L"Erreur lors du rendu de la broche EPG", hr); return hr; } if (FAILED(hr = render_pmtfilter(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu du pin pmt", hr); + erreur(L"Erreur lors du rendu de la broche PMT", hr); return hr; } @@ -1003,7 +1000,7 @@ HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IFilterGraph2, (void **)&pGraph); if (FAILED(hr) ) { - erreur(L"Pas réussi à créer le graph DirectShow !", hr); + erreur(L"Pas réussi à créer le graphe DirectShow !", hr); return hr; } @@ -1018,7 +1015,7 @@ #if EXPORT_GRAPH hr = AddToRot(); if (FAILED(hr)) { - erreur(L"échec de l'exportation du graphe", hr); + erreur(L"Échec de l'exportation du graphe", hr); return hr; } #endif // #if EXPORT_GRAPH @@ -1027,9 +1024,11 @@ CLSID clsid = {1,2,3,4,5,6,7,8,9,10,11}; IBaseFilter * pNetworkProvider = new CNetworkProvider(clsid); - hr = pGraph->AddFilter(pNetworkProvider, L"Fake"); + + if (pNetworkProvider) + hr = pGraph->AddFilter(pNetworkProvider, L"Fake"); if (FAILED(hr)) { - erreur(L"ajout du network provider ratée !!!", hr); + erreur(L"Échec de l'insertion du filtre \"CNetworkProvider\"", hr); return hr; } @@ -1043,27 +1042,27 @@ hr = pGraph->AddFilter(pNetworkTuner, L"Network Tuner"); if (FAILED(hr)) { - erreur(L"Tuner pas inséré", hr); + erreur(L"Échec de l'insertion du filtre Tuner", hr); return hr; } hr = pGraph->AddFilter(pReceiverComponent, L"Receiver Component"); if (FAILED(hr)) { - erreur(L"Récepteur pas inséré", hr); + erreur(L"Échec de l'insertion du filtre Récepteur", hr); return hr; } // connect Tuner hr = connect_filters(pNetworkProvider, pNetworkTuner); if (FAILED(hr)) { - erreur(L"Tuner TNT non compatible, veuillez effacer config.ini et redémarrer", hr); + erreur(L"Tuner TNT non compatible, veuillez effacer \"config.ini\" et redémarrer", hr); return hr; } // connect Receiver hr = connect_filters(pNetworkTuner, pReceiverComponent); if (FAILED(hr)) { - erreur(L"Récepteur TNT non compatible, veuillez effacer config.ini et redémarrer", hr); + erreur(L"Récepteur TNT non compatible, veuillez effacer \"config.ini\" et redémarrer", hr); return hr; } @@ -1077,13 +1076,13 @@ // connect USB hr = pGraph->AddFilter(pNetworkTuner, L"Tuner USB"); if (FAILED(hr)) { - erreur(L"Tuner USB pas inséré", hr); + erreur(L"Échec de l'insertion du filtre Tuner USB", hr); return hr; } hr = connect_filters(pNetworkProvider, pNetworkTuner); if (FAILED(hr)) { - erreur(L"Tuner USB non compatible, veuillez effacer config.ini et redémarrer", hr); + erreur(L"Tuner USB non compatible, veuillez effacer \"config.ini\" et redémarrer", hr); return hr; } @@ -1097,13 +1096,13 @@ hr = getFrequencyFilter(pNetworkTuner); if (FAILED(hr) || pBDAFreq == NULL) { - erreur(L"Pas trouvé l'interface pour changer de fréquence", hr); + erreur(L"L'interface de changement de fréquence n'a pas été trouvée", hr); return hr; } hr = getSignalStatistics(pNetworkTuner); if (FAILED(hr) || pStats == NULL) { - erreur(L"Pas trouvé l'interface pour avoir la qualité du signal", hr); + erreur(L"L'interface de qualité du signal n'a pas été trouvée", hr); return hr; } @@ -1111,24 +1110,21 @@ { // connect 3 - wchar_t nom[20]; - IBaseFilter *filtrePrec = pAvantDemux; filtrePrec->AddRef(); IBaseFilter * pGrabber; for (int i=0; iRelease(); - } // fin des recherches, ajoute tout dans le graph @@ -1165,7 +1157,7 @@ hr = cree_and_render_pins(); if (FAILED(hr)) { - erreur(L"Erreur lors de la création du graph", hr); + erreur(L"Erreur lors de la création du graphe", hr); return hr; } Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2008-11-07 23:19:57 UTC (rev 135) +++ trunk/main.cpp 2008-11-09 17:11:44 UTC (rev 136) @@ -962,7 +962,7 @@ if (Canaux.size() > 0) { restaure_chaine(sidChaineConfig); } else { - erreur(L"Aucune chaîne n'est dans le fichier"); + affiche_erreurs(L"Aucune chaîne n'est dans le fichier"); update_all_menus(hMainWnd); } @@ -1202,7 +1202,7 @@ static void create_property_dialog(IBaseFilter * pFilter, LPCOLESTR nom) { if (pFilter == NULL) { - erreur(L"Il faut d'abord configurer un filtre et redémarrer l'application"); + affiche_erreurs(L"Il faut d'abord configurer un filtre et redémarrer l'application"); return; } @@ -1210,7 +1210,7 @@ HRESULT hr = pFilter->QueryInterface(&pPages); if (FAILED(hr)) { - erreur(L"Ce filtre n'a pas de page de propriétés", hr); + affiche_erreurs(L"Ce filtre n'a pas de page de propriétés", hr); return; } @@ -1244,7 +1244,7 @@ CoTaskMemFree(caGUID.pElems); if (FAILED(hr)) { - erreur(L"Erreur lors de la création de la page de propriétés", hr); + affiche_erreurs(L"Erreur lors de la création de la page de propriétés", hr); } } @@ -2781,7 +2781,7 @@ HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); if (FAILED(hr)) { - erreur(L"Impossible d'initialiser la librairie COM."); + affiche_erreurs(L"Impossible d'initialiser la bibliothèque COM."); return hr; } @@ -2870,17 +2870,17 @@ if (!config_ok) { if (drivers_dialog()!=IDOK) { - erreur(L"Configuration annulée.\nLe logiciel ne peut pas être exécuté."); + affiche_erreurs(L"Configuration annulée.\nLe logiciel ne peut pas être exécuté."); return -1; } config_ok = check_config(); } if (!config_ok) { - erreur(L"Configuration incorrecte.\nVeuillez renseigner correctement tous les champs."); + affiche_erreurs(L"Configuration incorrecte.\nVeuillez renseigner correctement tous les champs."); continue; } else if (FAILED(hr = InitDshow())) { clean_dshow(); - erreur(L"Erreur lors de l'initialisation.\nVeuillez corriger la configuration.", hr); + affiche_erreurs(L"Erreur lors de l'initialisation.\nVeuillez corriger la configuration.", hr); config_ok = false; } } while (!config_ok); Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2008-11-07 23:19:57 UTC (rev 135) +++ trunk/recprog.cpp 2008-11-09 17:11:44 UTC (rev 136) @@ -210,7 +210,7 @@ wchar_t buffer[256]; if (ixChaine<0) { - erreur(L"La chaîne est incorrecte"); + affiche_erreurs(L"La chaîne est incorrecte"); return false; } @@ -219,27 +219,27 @@ long duree = DiffTime(fin, debut); if (duree < 0) { - erreur(L"Le programme commence après avoir fini !"); + affiche_erreurs(L"Le programme commence après avoir fini !"); return false; } if (duree == 0) { - erreur(L"La durée de l'enregistrement est nulle !"); + affiche_erreurs(L"La durée de l'enregistrement est nulle !"); return false; } if (duree > 12*60*60*1000) { - erreur(L"La durée de l'enregistrement dépasse 12 heures !"); + affiche_erreurs(L"La durée de l'enregistrement dépasse 12 heures !"); return false; } if (DiffTime(fin, localtime) < 0) { - erreur(L"L'heure de fin du programme est dépassée !"); + affiche_erreurs(L"L'heure de fin du programme est dépassée !"); return false; } if (nom[0] == 0) { - erreur(L"Veuillez donner un nom à ce programme"); + affiche_erreurs(L"Veuillez donner un nom à ce programme"); return false; } @@ -251,7 +251,7 @@ if (!modif) { if (strcmp(prog_verif.nom, nom) == 0) { - erreur(L"Ce nom est déjà utilisé"); + affiche_erreurs(L"Ce nom est déjà utilisé"); return false; } } @@ -264,7 +264,7 @@ swprintf_s(buffer, _countof(buffer), L"Chevauchement des horaires avec \"%S\", qui concerne la même chaîne !", prog_verif.nom); - erreur(buffer); + affiche_erreurs(buffer); return false; } @@ -273,7 +273,7 @@ swprintf_s(buffer, _countof(buffer), L"Chevauchement des horaires avec \"%S\" sur %S, qui ne partage pas le même multiplex !", prog_verif.nom, canal.nom); - erreur(buffer); + affiche_erreurs(buffer); return false; } } Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2008-11-07 23:19:57 UTC (rev 135) +++ trunk/res.rc 2008-11-09 17:11:44 UTC (rev 136) @@ -176,12 +176,12 @@ GROUPBOX "Avancé",IDC_STATIC,7,85,276,24 CONTROL "Permettre l'enregistrement intégral du multiplex courant",IDC_ALLOW_STREAM_RECORD, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,95,262,10 - GROUPBOX "Divers",IDC_STATIC,7,178,276,29 - CONTROL "Afficher le nom de l'émission sous MSN",IDC_MSN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,190,262,10 GROUPBOX "Nom des enregistrements",IDC_STATIC,7,110,276,67 EDITTEXT IDC_NOM_REC,14,121,261,12,ES_AUTOHSCROLL LTEXT "%c = chaine\n%e = nom de l'enregistrement",IDC_STATIC,14,135,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,158,262,17 + GROUPBOX "Divers",IDC_STATIC,7,178,276,29 + CONTROL "Afficher le nom de l'émission sous MSN",IDC_MSN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,190,262,10 END IDD_FOLDERS DIALOGEX 0, 0, 290, 214 Modifié: trunk/search.cpp =================================================================== --- trunk/search.cpp 2008-11-07 23:19:57 UTC (rev 135) +++ trunk/search.cpp 2008-11-09 17:11:44 UTC (rev 136) @@ -132,7 +132,7 @@ } -IBaseFilter * get_filter(GUID type, GUID subtype, wchar_t * nom) +HRESULT get_filter(GUID type, GUID subtype, LPCWSTR nom, IBaseFilter * & pFilter) { myprintf(L"get_filter: type={%08x-%04x-%04x-%012x}\n", type.Data1, type.Data2, type.Data3, type.Data4); myprintf(L"\tsubtype={%08x-%04x-%04x-%012x}\n", subtype.Data1, subtype.Data2, subtype.Data3, subtype.Data4); @@ -140,11 +140,13 @@ IFilterMapper2 * pMapper; + pFilter = NULL; + HRESULT hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC, IID_IFilterMapper2, (void **)&pMapper); if (FAILED(hr)) { myprintf(L"get_filter, 1, hr=0x%08x\n", hr); - return NULL; + return hr; } GUID arrayInTypes[2]; @@ -173,13 +175,12 @@ if (FAILED(hr)) { myprintf(L"get_filter, 2, hr=0x%08x\n", hr); pMapper->Release(); - return NULL; + return hr; } // Enumerate the monikers. IMoniker *pMoniker; ULONG cFetched; - IBaseFilter *pFilter = NULL; while (pFilter == NULL && pEnum->Next(1, &pMoniker, &cFetched) == S_OK) { IPropertyBag * pPropBag; @@ -208,7 +209,7 @@ pEnum->Release(); pMapper->Release(); - return pFilter; + return hr; } // 1er pin non connecté Modifié: trunk/search.h =================================================================== --- trunk/search.h 2008-11-07 23:19:57 UTC (rev 135) +++ trunk/search.h 2008-11-09 17:11:44 UTC (rev 136) @@ -31,7 +31,7 @@ HRESULT cherche_pin(IBaseFilter * pFilter, PIN_DIRECTION dir, IPin * & result); void search_filters(GUID type, GUID subtype, HWND hItm); -IBaseFilter * get_filter(GUID type, GUID subtype, wchar_t * nom); +HRESULT get_filter(GUID type, GUID subtype, LPCWSTR nom, IBaseFilter * & pFilter); HRESULT remplit_tuners(GUID guid, HWND hItm); IBaseFilter * get_tuner(GUID guid, wchar_t * nom); Modifié: trunk/settings.cpp =================================================================== --- trunk/settings.cpp 2008-11-07 23:19:57 UTC (rev 135) +++ trunk/settings.cpp 2008-11-09 17:11:44 UTC (rev 136) @@ -288,7 +288,7 @@ switch (scanState) { case ss_idle: if (nomVille[0]==0) { - erreur(L"Veuillez d'abord sélectionner une ville"); + affiche_erreurs(L"Veuillez d'abord sélectionner une ville"); break; } zappe_index(-1); @@ -425,7 +425,7 @@ if (Canaux.empty()) { static LPCWSTR msg_aucune = L"Aucune chaîne n'a été trouvée"; - erreur(msg_aucune); + affiche_erreurs(msg_aucune); AddLineToList(hListItem, msg_aucune); } else { do_init_vmr(); From pouchintv-dev at baysse.fr Sun Nov 9 20:48:50 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sun, 9 Nov 2008 20:48:50 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r137 - trunk Message-ID: <20081109194850.930125F331@mail.baysse.fr> Author: gingko Date: 2008-11-09 20:48:50 +0100 (dim, 09 nov 2008) New Revision: 137 Modified: trunk/base.h trunk/graph.cpp trunk/graph.h Log: Utilisation d'une macro de concaténation pour produire certains changements d'identificateurs entre le VMR7 et le VMR9, évitant ainsi de devoir définir un nouveau symbole pour chaque nouvel identificateur modifié qu'on souhaite utiliser. Modifié: trunk/base.h =================================================================== --- trunk/base.h 2008-11-09 17:11:44 UTC (rev 136) +++ trunk/base.h 2008-11-09 19:48:50 UTC (rev 137) @@ -67,9 +67,7 @@ #include "resource.h" // Décommenter si on veut afficher la console de debugging : -//#undef USE_CONSOLE //#define USE_CONSOLE 1 -//#define USE_CONSOLE -1 // // On peut aussi mettre USE_CONSOLE=-1, afin d'envoyer les messages // d'erreur vers la fonction OutputDebugString, pour ensuite les @@ -125,56 +123,26 @@ #if USE_VMR9 -#define MyIVMRWindowlessControl IVMRWindowlessControl9 -#define MyIID_IVMRWindowlessControl IID_IVMRWindowlessControl9 -#define MyCLSID_VideoMixingRenderer CLSID_VideoMixingRenderer9 + #define MyV(a) a ## 9 -#define MyIVMRFilterConfig IVMRFilterConfig9 -#define MyIID_IVMRFilterConfig IID_IVMRFilterConfig9 + #define MyVMRVideoDesc VMR9VideoDesc -#define MyIVMRMixerControl IVMRMixerControl9 -#define MyIID_IVMRMixerControl IID_IVMRMixerControl9 + #define MyVMRMode_Windowless VMR9Mode_Windowless + #define MyVMRMode_Renderless VMR9Mode_Renderless -#define MyIVMRDeinterlaceControl IVMRDeinterlaceControl9 -#define MyIID_IVMRDeinterlaceControl IID_IVMRDeinterlaceControl9 + #define MyMIXINGPREFS (MixerPref9_NoDecimation | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetYUV) -#define MyIVMRAspectRatioControl IVMRAspectRatioControl9 -#define MyIID_IVMRAspectRatioControl IID_IVMRAspectRatioControl9 - -#define MyVMRVideoDesc VMR9VideoDesc - -#define MyVMRMode_Windowless VMR9Mode_Windowless - -#define MyVMRMode_Renderless VMR9Mode_Renderless - -#define MyMixingPrefs (MixerPref9_NoDecimation | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetYUV) - #else // #if USE_VMR9 -#define MyIVMRWindowlessControl IVMRWindowlessControl -#define MyIID_IVMRWindowlessControl IID_IVMRWindowlessControl -#define MyCLSID_VideoMixingRenderer CLSID_VideoMixingRenderer + #define MyV(a) a -#define MyIVMRFilterConfig IVMRFilterConfig -#define MyIID_IVMRFilterConfig IID_IVMRFilterConfig + #define MyVMRVideoDesc VMRVideoDesc -#define MyIVMRMixerControl IVMRMixerControl -#define MyIID_IVMRMixerControl IID_IVMRMixerControl + #define MyVMRMode_Windowless VMRMode_Windowless + #define MyVMRMode_Renderless VMRMode_Renderless -#define MyIVMRDeinterlaceControl IVMRDeinterlaceControl -#define MyIID_IVMRDeinterlaceControl IID_IVMRDeinterlaceControl + #define MyMIXINGPREFS (MixerPref_NoDecimation | MixerPref_BiLinearFiltering | MixerPref_RenderTargetYUV) -#define MyIVMRAspectRatioControl IVMRAspectRatioControl -#define MyIID_IVMRAspectRatioControl IID_IVMRAspectRatioControl - -#define MyVMRVideoDesc VMRVideoDesc - -#define MyVMRMode_Windowless VMRMode_Windowless - -#define MyVMRMode_Renderless VMRMode_Renderless - -#define MyMixingPrefs (MixerPref_NoDecimation | MixerPref_BiLinearFiltering | MixerPref_RenderTargetYUV) - #endif // #if USE_VMR9 // Macros utilitaires pour améliorer la lisibilité du code : Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2008-11-09 17:11:44 UTC (rev 136) +++ trunk/graph.cpp 2008-11-09 19:48:50 UTC (rev 137) @@ -40,7 +40,7 @@ IFilterGraph2 * pGraph = NULL; IMediaControl * pControl = NULL; -MyIVMRWindowlessControl * pVMRControl = NULL; +MyV(IVMRWindowlessControl) * pVMRControl = NULL; IBaseFilter * pDemux = NULL; @@ -392,12 +392,12 @@ // crée le VMR - hr = create_and_add_filter(MyCLSID_VideoMixingRenderer, L"Mon VMR", pVMR); + hr = create_and_add_filter(MyV(CLSID_VideoMixingRenderer), L"Video Mixing Renderer", pVMR); if (FAILED(hr)) return hr; { - MyIVMRFilterConfig * pVMRConfig; + MyV(IVMRFilterConfig) * pVMRConfig; hr = pVMR->QueryInterface(&pVMRConfig); if (FAILED(hr)) { erreur(L"L'interface de configuration VMR n'est pas disponible", hr); @@ -420,18 +420,18 @@ #if !USE_VMR9 // Modif R_One - à revérifier { - IVMRSurfaceAllocatorNotify * pNotify; + MyV(IVMRSurfaceAllocatorNotify) * pNotify; hr = pVMR->QueryInterface(&pNotify); if (FAILED(hr)) { erreur(L"L'interface IVMRSurfaceAllocatorNotify n'a pas été trouvée", hr); return hr; } - IVMRSurfaceAllocator * pSurfAlloc; + MyV(IVMRSurfaceAllocator) * pSurfAlloc = NULL; hr = CoCreateInstance(CLSID_AllocPresenter, NULL, CLSCTX_INPROC_SERVER, - IID_IVMRSurfaceAllocator, + MyV(IID_IVMRSurfaceAllocator), (LPVOID*)&pSurfAlloc); if (FAILED(hr)) { @@ -439,7 +439,7 @@ return hr; } - IVMRImagePresenterConfig * pPresConf = NULL; + MyV(IVMRImagePresenterConfig) * pPresConf = NULL; hr = pSurfAlloc->QueryInterface(&pPresConf); if (FAILED(hr)) { @@ -464,7 +464,7 @@ if (use_vmr_deinterlace) { - MyIVMRMixerControl * pMixControl; + MyV(IVMRMixerControl) * pMixControl; hr = pVMR->QueryInterface(&pMixControl); if (FAILED(hr)) { @@ -472,14 +472,14 @@ return hr; } - hr = pMixControl->SetMixingPrefs(MyMixingPrefs); + hr = pMixControl->SetMixingPrefs(MyMIXINGPREFS); pMixControl->Release(); if (FAILED(hr)) { erreur(L"Échec de SetMixingPrefs", hr); return hr; } - MyIVMRDeinterlaceControl * pDeint; + MyV(IVMRDeinterlaceControl) * pDeint; hr = pVMR->QueryInterface(&pDeint); if (FAILED(hr)) { erreur(L"L'interface IVMRDeinterlaceControl n'a pas été trouvée", hr); @@ -548,7 +548,7 @@ #endif { - MyIVMRAspectRatioControl * pARC; + MyV(IVMRAspectRatioControl) * pARC; hr = pVMR->QueryInterface(&pARC); if (FAILED(hr)) { Modifié: trunk/graph.h =================================================================== --- trunk/graph.h 2008-11-09 17:11:44 UTC (rev 136) +++ trunk/graph.h 2008-11-09 19:48:50 UTC (rev 137) @@ -42,7 +42,7 @@ extern IBaseFilter * pNetworkTuner; extern IBaseFilter * pReceiverComponent; -extern MyIVMRWindowlessControl * pVMRControl; +extern MyV(IVMRWindowlessControl) * pVMRControl; extern IBDA_SignalStatistics * pStats; extern IBDA_DeviceControl * pBDAControl; From pouchintv-dev at baysse.fr Sun Nov 9 23:21:51 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sun, 9 Nov 2008 23:21:51 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r138 - trunk Message-ID: <20081109222151.CA1CD6EEF3@mail.baysse.fr> Author: gingko Date: 2008-11-09 23:21:51 +0100 (dim, 09 nov 2008) New Revision: 138 Modified: trunk/epgfilter.cpp trunk/epgfilter.h trunk/graph.cpp trunk/network.cpp trunk/network.h trunk/pmtfilter.cpp trunk/pmtfilter.h Log: Normalisation des classes CNetworkProvider, CPMTFilter et CEPGFilter : attribution de vrais CLSID (générés avec "guidgen.exe") à la place des CLSID non conformes précédemment utilisés, définition d'interfaces de création identiques (en vue d'un usage éventuel dans CFactoryTemplate). Utilisation de noms de filtres plus proches des noms réels de ces filtres. Modifié: trunk/epgfilter.cpp =================================================================== --- trunk/epgfilter.cpp 2008-11-09 19:48:50 UTC (rev 137) +++ trunk/epgfilter.cpp 2008-11-09 22:21:51 UTC (rev 138) @@ -33,15 +33,15 @@ #include "crc32.h" #include "mpeg2defs.h" -CEPGFilter::CEPGFilter(REFCLSID clsid, HRESULT *phr) : CBaseRenderer(clsid, L"filtre EPG", NULL, phr) +CEPGFilter::CEPGFilter(IUnknown *pUnk, HRESULT *phr) : + CBaseRenderer(__uuidof(this), szFilterName, pUnk, phr) { - myprintf(L"EPG filter construit\n"); + myprintf(L"%s construit\n", szFilterName); } - CEPGFilter::~CEPGFilter() { - myprintf(L"EPG filter detruit\n"); + myprintf(L"%s detruit\n", szFilterName); } // Nettoyage des codes spéciaux (codes 0x80 à 0x9f) dans la chaîne, @@ -70,6 +70,22 @@ *dst = 0; } +LPCTSTR CEPGFilter::szFilterName = TEXT("Filtre EPG PTvM"); + +CUnknown * WINAPI CEPGFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr) // static +{ + CEPGFilter *pNewFilter = new CEPGFilter(pUnk, phr); + + if (phr) { + if (pNewFilter == NULL) + *phr = E_OUTOFMEMORY; + else + *phr = S_OK; + } + + return pNewFilter; +} + static void parse_eit(const SI_EIT & eit, size_t size) { bool modif = false; Modifié: trunk/epgfilter.h =================================================================== --- trunk/epgfilter.h 2008-11-09 19:48:50 UTC (rev 137) +++ trunk/epgfilter.h 2008-11-09 22:21:51 UTC (rev 138) @@ -29,16 +29,17 @@ #include +[uuid("3A81A9CF-606B-458f-8244-9DC73128C79E")] class CEPGFilter : public CBaseRenderer { - public: - CEPGFilter(REFCLSID clsid, HRESULT *phr); + CEPGFilter(IUnknown *pUnk, HRESULT *phr); ~CEPGFilter(); // Derived classes MUST override these HRESULT DoRenderSample(IMediaSample *pMediaSample); HRESULT CheckMediaType(const CMediaType *pmt); + static LPCTSTR szFilterName; + static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr); }; - Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2008-11-09 19:48:50 UTC (rev 137) +++ trunk/graph.cpp 2008-11-09 22:21:51 UTC (rev 138) @@ -351,7 +351,7 @@ if (SUCCEEDED(hr)) { myprintf(L"Ajout video MPEG2\n"); - hr = pGraph->AddFilter(pVideoCodec, L"Codec vidéo"); + hr = pGraph->AddFilter(pVideoCodec, filtreMPEG2); if (FAILED(hr)) { erreur(L"Le codec vidéo MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreMPEG2); return hr; @@ -429,10 +429,10 @@ MyV(IVMRSurfaceAllocator) * pSurfAlloc = NULL; - hr = CoCreateInstance(CLSID_AllocPresenter, NULL, - CLSCTX_INPROC_SERVER, + hr = CoCreateInstance( CLSID_AllocPresenter, NULL, + CLSCTX_INPROC_SERVER, MyV(IID_IVMRSurfaceAllocator), - (LPVOID*)&pSurfAlloc); + (LPVOID*)&pSurfAlloc); if (FAILED(hr)) { erreur(L"L'interface IVMRSurfaceAllocator n'a pas été trouvée", hr); @@ -611,7 +611,7 @@ } // add direct sound - hr = create_and_add_filter(CLSID_DSoundRender, L"Direct sound", pDSound); + hr = create_and_add_filter(CLSID_DSoundRender, L"DirectSound (MPEG2)", pDSound); if (FAILED(hr)) return hr; @@ -621,7 +621,7 @@ myprintf(L"ajout audio\n"); - hr = pGraph->AddFilter(pAudioCodec, L"Codec audio"); + hr = pGraph->AddFilter(pAudioCodec, filtreAudio); if (FAILED(hr)) { erreur(L"Le codec audio MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAudio); @@ -696,7 +696,7 @@ } // add direct sound - hr = create_and_add_filter(CLSID_DSoundRender, L"Direct sound le retour", pDSoundAc3); + hr = create_and_add_filter(CLSID_DSoundRender, L"DirectSound (AC3)", pDSoundAc3); if (FAILED(hr)) return hr; @@ -706,7 +706,7 @@ myprintf(L"ajout ac3\n"); - hr = pGraph->AddFilter(pAc3Codec, L"Codec ac3"); + hr = pGraph->AddFilter(pAc3Codec, filtreAc3); if (FAILED(hr)) { erreur(L"Le codec audio AC3 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAc3); @@ -774,7 +774,7 @@ { IBaseFilter * pMpeg2Filter = NULL; - hr = create_and_add_filter(__uuidof(Mpeg2Data), L"MPEG2 data", pMpeg2Filter); + hr = create_and_add_filter(__uuidof(Mpeg2Data), L"MPEG-2 Sections and Tables", pMpeg2Filter); if (FAILED(hr)) return hr; @@ -791,8 +791,8 @@ hr = cherche_pin(pMpeg2Filter, PINDIR_INPUT, pPinEntree); if (SUCCEEDED(hr) && pPinEntree!=NULL) { - hr = pGraph->ConnectDirect(pDataPin, pPinEntree, NULL); - pPinEntree->Release(); + hr = pGraph->ConnectDirect(pDataPin, pPinEntree, NULL); + pPinEntree->Release(); } if (FAILED(hr)) { @@ -832,14 +832,14 @@ // add mpeg2 { - CLSID clsid = {5, 6, 7, 8, 9, 10, 11, 12, 13}; - CEPGFilter * pEPGFilter = new CEPGFilter(clsid, &hr); + CEPGFilter * pEPGFilter = + dynamic_cast (CEPGFilter::CreateInstance(NULL, &hr)); if (FAILED(hr)) { erreur(L"Le filtre EPG n'a pas pu être créé", hr); return hr; } - hr = pGraph->AddFilter(pEPGFilter, L"Mon filtre EPG"); + hr = pGraph->AddFilter(pEPGFilter, CEPGFilter::szFilterName); if (FAILED(hr)) { erreur(L"Le filtre EPG n'a pas pu être ajouté au graphe", hr); return hr; @@ -899,15 +899,16 @@ // add mpeg2 { - CLSID clsid = {6, 7, 8, 9, 10, 11, 12, 13, 14}; - CPMTFilter * pPMTFilter = new CPMTFilter(clsid, &hr); + // CLSID clsid = {6, 7, 8, 9, 10, 11, 12, 13, 14}; + CPMTFilter * pPMTFilter = + dynamic_cast(CPMTFilter::CreateInstance(NULL, &hr)); // new CPMTFilter(clsid, &hr); - if (FAILED(hr) || pPMTFilter == NULL) { + if (FAILED(hr)) { erreur(L"Le filtre PMT n'a pas pu être créé", hr); return hr; } - hr = pGraph->AddFilter(pPMTFilter, L"Mon filtre PMT"); + hr = pGraph->AddFilter(pPMTFilter, CPMTFilter::szFilterName); if (FAILED(hr)) { erreur(L"Le filtre PMT n'a pas pu être ajouté au graphe", hr); return hr; @@ -1022,13 +1023,13 @@ { // filtre dvb-t - CLSID clsid = {1,2,3,4,5,6,7,8,9,10,11}; - IBaseFilter * pNetworkProvider = new CNetworkProvider(clsid); - - if (pNetworkProvider) - hr = pGraph->AddFilter(pNetworkProvider, L"Fake"); + IBaseFilter * pNetworkProvider = + dynamic_cast(CNetworkProvider::CreateInstance(NULL, &hr)); + + if (SUCCEEDED(hr)) + hr = pGraph->AddFilter(pNetworkProvider, CNetworkProvider::szFilterName); if (FAILED(hr)) { - erreur(L"Échec de l'insertion du filtre \"CNetworkProvider\"", hr); + erreur(L"Échec de l'insertion du filtre Network Provider", hr); return hr; } @@ -1040,13 +1041,13 @@ // PCI - hr = pGraph->AddFilter(pNetworkTuner, L"Network Tuner"); + hr = pGraph->AddFilter(pNetworkTuner, nom_tuner); if (FAILED(hr)) { erreur(L"Échec de l'insertion du filtre Tuner", hr); return hr; } - hr = pGraph->AddFilter(pReceiverComponent, L"Receiver Component"); + hr = pGraph->AddFilter(pReceiverComponent, nom_receiver); if (FAILED(hr)) { erreur(L"Échec de l'insertion du filtre Récepteur", hr); return hr; @@ -1074,7 +1075,7 @@ // USB // connect USB - hr = pGraph->AddFilter(pNetworkTuner, L"Tuner USB"); + hr = pGraph->AddFilter(pNetworkTuner, nom_tuner); if (FAILED(hr)) { erreur(L"Échec de l'insertion du filtre Tuner USB", hr); return hr; @@ -1135,7 +1136,7 @@ // connect 4 - hr = create_and_add_filter(CLSID_MPEG2Demultiplexer, L"Demux", pDemux); + hr = create_and_add_filter(CLSID_MPEG2Demultiplexer, L"MPEG2 Demultiplexer", pDemux); if (FAILED(hr)) return hr; Modifié: trunk/network.cpp =================================================================== --- trunk/network.cpp 2008-11-09 19:48:50 UTC (rev 137) +++ trunk/network.cpp 2008-11-09 22:21:51 UTC (rev 138) @@ -36,16 +36,14 @@ } -HRESULT -CPinBidon::CheckMediaType(const CMediaType *pmt) +HRESULT CPinBidon::CheckMediaType(const CMediaType *pmt) { // myprintf(L"CheckMediaType\n"); if ( *pmt->Type() == KSDATAFORMAT_TYPE_BDA_ANTENNA) return S_OK; return S_FALSE; } -HRESULT -CPinBidon::GetMediaType(int iPosition, CMediaType *pMediaType) +HRESULT CPinBidon::GetMediaType(int iPosition, CMediaType *pMediaType) { myprintf(L"GetMediaType %i\n", iPosition); if (iPosition == 0) { @@ -60,35 +58,56 @@ } -HRESULT -CPinBidon::FillBuffer(IMediaSample *pSamp) { +HRESULT CPinBidon::FillBuffer(IMediaSample *pSamp) { //myprintf(L"CPinBidon FillBuffer\n"); return S_OK; } -HRESULT -CPinBidon::DecideBufferSize(IMemAllocator * pAlloc,ALLOCATOR_PROPERTIES * ppropInputRequest) +HRESULT CPinBidon::DecideBufferSize(IMemAllocator * pAlloc,ALLOCATOR_PROPERTIES * ppropInputRequest) { //myprintf(L"CPinBidon DecideBufferSize\n"); return S_OK; } -CNetworkProvider::CNetworkProvider(CLSID clsid) : - CSource(L"Mon network provider", NULL, clsid) +CNetworkProvider::CNetworkProvider(IUnknown *pUnk, HRESULT *phr) : + CSource(szFilterName, NULL, __uuidof(this)) { HRESULT hr; m_bidon = new CPinBidon(&hr, this); - myprintf(L"network construit\n"); + if (phr) { + if (m_bidon == NULL) + *phr = E_OUTOFMEMORY; + else { + *phr = S_OK; + myprintf(TEXT("%s construit\n"), szFilterName); + } + } } CNetworkProvider::~CNetworkProvider() { - myprintf(L"network detruit\n"); + myprintf(TEXT("%s detruit\n"), szFilterName); delete m_bidon; } +LPCTSTR CNetworkProvider::szFilterName = TEXT("Network Provider PTvM"); + +CUnknown * WINAPI CNetworkProvider::CreateInstance(IUnknown *pUnk, HRESULT *phr) // static +{ + CNetworkProvider *pNewFilter = new CNetworkProvider(pUnk, phr); + + if (phr) { + if (pNewFilter == NULL) + *phr = E_OUTOFMEMORY; + else + *phr = S_OK; + } + + return pNewFilter; +} + // // GetPinCount // Modifié: trunk/network.h =================================================================== --- trunk/network.h 2008-11-09 19:48:50 UTC (rev 137) +++ trunk/network.h 2008-11-09 22:21:51 UTC (rev 138) @@ -46,16 +46,19 @@ }; +[uuid("1436DC04-A20F-46a7-B9FA-CF3C95A1E00C")] class CNetworkProvider : public CSource { private: CPinBidon * m_bidon; public: - CNetworkProvider(CLSID clsid); + CNetworkProvider(IUnknown *pUnk, HRESULT *phr); ~CNetworkProvider(); int GetPinCount(void); CBasePin *GetPin(int n); + static LPCTSTR szFilterName; + static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr); }; Modifié: trunk/pmtfilter.cpp =================================================================== --- trunk/pmtfilter.cpp 2008-11-09 19:48:50 UTC (rev 137) +++ trunk/pmtfilter.cpp 2008-11-09 22:21:51 UTC (rev 138) @@ -36,17 +36,33 @@ #include "crc32.h" -CPMTFilter::CPMTFilter(REFCLSID clsid, HRESULT *phr) : CBaseRenderer(clsid, L"filtre EPG", NULL, phr) +CPMTFilter::CPMTFilter(IUnknown *pUnk, HRESULT *phr) : + CBaseRenderer(__uuidof(this), szFilterName, pUnk, phr) { - myprintf(L"PMT filter construit\n"); + myprintf(TEXT("%s construit\n"), szFilterName); } - CPMTFilter::~CPMTFilter() { - myprintf(L"PMT filter detruit\n"); + myprintf(TEXT("%s detruit\n"), szFilterName); } +LPCTSTR CPMTFilter::szFilterName = TEXT("Filtre PMT PTvM"); + +CUnknown * WINAPI CPMTFilter::CreateInstance(IUnknown *pUnk, HRESULT *phr) // static +{ + CPMTFilter *pNewFilter = new CPMTFilter(pUnk, phr); + + if (phr) { + if (pNewFilter == NULL) + *phr = E_OUTOFMEMORY; + else + *phr = S_OK; + } + + return pNewFilter; +} + HRESULT CPMTFilter::DoRenderSample(IMediaSample *pMediaSample) { const SI_PMT * ppmt; Modifié: trunk/pmtfilter.h =================================================================== --- trunk/pmtfilter.h 2008-11-09 19:48:50 UTC (rev 137) +++ trunk/pmtfilter.h 2008-11-09 22:21:51 UTC (rev 138) @@ -29,16 +29,17 @@ #include +[uuid("A72DA4DF-8931-4598-97C5-0AB895EEB356")] class CPMTFilter : public CBaseRenderer { - public: - CPMTFilter(REFCLSID clsid, HRESULT *phr); + CPMTFilter(IUnknown *pUnk, HRESULT *phr); ~CPMTFilter(); // Derived classes MUST override these HRESULT DoRenderSample(IMediaSample *pMediaSample); HRESULT CheckMediaType(const CMediaType *pmt); + static LPCTSTR szFilterName; + static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr); }; - From pouchintv-dev at baysse.fr Tue Nov 11 01:27:21 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Tue, 11 Nov 2008 01:27:21 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r139 - trunk Message-ID: <20081111002721.4B5485F331@mail.baysse.fr> Author: gingko Date: 2008-11-11 01:27:20 +0100 (mar, 11 nov 2008) New Revision: 139 Modified: trunk/LCD.cpp trunk/base.cpp trunk/base.h trunk/channels.cpp trunk/graph.cpp trunk/graph.h trunk/ini.cpp trunk/main.cpp trunk/network.cpp trunk/pmtfilter.cpp trunk/record.cpp trunk/record.h trunk/recprog.cpp trunk/search.cpp trunk/search.h trunk/utils.h trunk/xml.cpp trunk/xml.h Log: Réécriture des déclarations d'instances d'objets issus des filtres DirectShow, ainsi que d'autres objets dérivés du modèle d'objets COM, de manière à utiliser les "smart pointers" définis dans la bibliothèques de modèles de classes (templates) ATL. Ces classes gérant automatiquement les ajouts et suppressions de références de ces objets (AddRef et Release), ceci permet de supprimer la plupart de ces instructions, tout en s'assurant d'une gestion optimale de ces objets avec réduction au minimum des risques de fuites de mémoires et d'objets non détruits. Ajout d'un nouvel appel redondant à "CoInitializeEx" en cas d'échec de de la création du graphe, en raison du fait que certains filtres DirectShow (Nero...) semblent s'autoprotéger contre les usages non autorisés en exécutant une instruction "CoUninitialize", ce qui compliquait sérieusement le retour subséquent au dialogue de configuration. Optimisation supplémentaire de la gestion des messages d'erreurs (via ajout d'une recopie du code d'erreur transmis à la fonction "erreur" vers la valeur de retour de cette fonction). Modifié: trunk/LCD.cpp =================================================================== --- trunk/LCD.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/LCD.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -24,9 +24,6 @@ // // Il faut simplement installer les pilotes du clavier logitech G15 ou des enceintes Z10 -#include -#include - #include "base.h" #include "main.h" #include "LCD.h" Modifié: trunk/base.cpp =================================================================== --- trunk/base.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/base.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -34,12 +34,12 @@ static LPWSTR pszErrBuf = NULL; static HRESULT lastRes = S_OK; -void erreur(LPCWSTR str, HRESULT hr, ...) +HRESULT erreur(LPCWSTR str, HRESULT hr, ...) { - LPWSTR pszNewErrBuf; WCHAR buffer[0x200]; if (str) { + LPWSTR pszNewErrBuf; va_list argptr; va_start(argptr, hr); @@ -62,15 +62,16 @@ pszNewErrBuf = new WCHAR[nBufLen]; wcscpy_s(pszNewErrBuf, nBufLen, buffer); } + pszErrBuf = pszNewErrBuf; } - pszErrBuf = pszNewErrBuf; - if (hr!=S_OK && hr!=lastRes) { + if (FAILED(hr) && hr!=lastRes) { AMGetErrorText(hr, buffer, _countof(buffer)); erreur(L"%s (code 0x%08x)", S_OK, buffer, hr); lastRes = hr; } + return hr; } void affiche_erreurs(LPCWSTR str, HRESULT hr) Modifié: trunk/base.h =================================================================== --- trunk/base.h 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/base.h 2008-11-11 00:27:20 UTC (rev 139) @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -64,6 +65,8 @@ #pragma warning(disable:4995) #include +#include + #include "resource.h" // Décommenter si on veut afficher la console de debugging : @@ -175,5 +178,5 @@ etf_minimized // minimisée (en icône ou pas) }; -void erreur(LPCWSTR str, HRESULT hr, ...); +HRESULT erreur(LPCWSTR str, HRESULT hr, ...); void affiche_erreurs(LPCWSTR str, HRESULT hr=S_OK); Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/channels.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -253,7 +253,7 @@ // S'assurer que le VMR a été initialisé : bool do_init_vmr() { - if (pVMRControl == NULL) { + if (!pVMRControl) { HRESULT hr = init_vmr(); if (FAILED(hr)) { @@ -265,17 +265,18 @@ return true; } -static void debranche_tout(IMPEG2PIDMap * pMap) +static void debranche_tout(CComPtr & pMap) { - IEnumPIDMap * pEnumMap; - pMap->EnumPIDMap(&pEnumMap); - PID_MAP maps[8]; - ULONG nbPids; - pEnumMap->Next(8, maps, &nbPids); + ULONG nbPids; - pEnumMap->Release(); + { + CComPtr pEnumMap; + pMap->EnumPIDMap(&pEnumMap); + pEnumMap->Next(_countof(maps), maps, &nbPids); + } + for (ULONG i=0; iUnmapPID(1, &maps[i].ulPID); myprintf(L"%?unmap foiré, hr=0x%08x\n", FAILED(hr), hr); @@ -407,13 +408,8 @@ void set_volume(long volume) { - IBasicAudio * pBas; + CComQIPtr pBas(pGraph); - HRESULT hr = pGraph->QueryInterface(&pBas); - - myprintf(L"%?erreur set_volume, hr=0x%08x\n", FAILED(hr), hr); - if (SUCCEEDED(hr)) { + if (pBas) pBas->put_Volume(volume); - pBas->Release(); - } } Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/graph.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -37,35 +37,35 @@ #include -IFilterGraph2 * pGraph = NULL; -IMediaControl * pControl = NULL; +CComPtr pGraph; +CComPtr pControl; -MyV(IVMRWindowlessControl) * pVMRControl = NULL; +CComPtr pVMRControl; -IBaseFilter * pDemux = NULL; +CComPtr pDemux; -IBaseFilter * pVideoCodec = NULL; -IBaseFilter * pAudioCodec = NULL; -IBaseFilter * pAc3Codec = NULL; +CComPtr pVideoCodec; +CComPtr pAudioCodec; +CComPtr pAc3Codec; -IBaseFilter * pVMR = NULL; -IBaseFilter * pDSound = NULL; -IBaseFilter * pDSoundAc3 = NULL; +CComPtr pVMR; +CComPtr pDSound; +CComPtr pDSoundAc3; -IMPEG2PIDMap * pMapMPEG2 = NULL; -IMPEG2PIDMap * pMapH264 = NULL; -IMPEG2PIDMap * pMapSound = NULL; -IMPEG2PIDMap * pMapAc3 = NULL; -IMPEG2PIDMap * pMapPmt = NULL; +CComPtr pMapMPEG2; +CComPtr pMapH264; +CComPtr pMapSound; +CComPtr pMapAc3; +CComPtr pMapPmt; -IMpeg2Data * pMpeg2Data = NULL; +CComPtr pMpeg2Data; -IBaseFilter * pNetworkTuner = NULL; -IBaseFilter * pReceiverComponent = NULL; +CComPtr pNetworkTuner; +CComPtr pReceiverComponent; -IBDA_DeviceControl * pBDAControl; -IBDA_FrequencyFilter * pBDAFreq; -IBDA_SignalStatistics * pStats; +CComPtr pBDAControl; +CComPtr pBDAFreq; +CComPtr pStats; bool use_vmr_deinterlace = false; @@ -75,32 +75,30 @@ static HRESULT AddToRot() { - IMoniker * pMoniker = NULL; - IRunningObjectTable *pROT = NULL; + CComPtr pMoniker; + CComPtr pROT; + WCHAR wsz[256]; - if (FAILED(GetRunningObjectTable(0, &pROT))) { + if (FAILED(GetRunningObjectTable(0, &pROT))) return E_FAIL; - } - WCHAR wsz[256]; - StringCchPrintfW(wsz, _countof(wsz), L"FilterGraph %08x pid %08x", (DWORD_PTR)pGraph, GetCurrentProcessId()); + StringCchPrintfW(wsz, _countof(wsz), L"FilterGraph %08x pid %08x", (DWORD_PTR)&pGraph.p, GetCurrentProcessId()); + HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker); - if (SUCCEEDED(hr)) { + + if (SUCCEEDED(hr)) hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pGraph, - pMoniker, &pdwRegister); - pMoniker->Release(); - } - pROT->Release(); + pMoniker, &pdwRegister); + return hr; } static void RemoveFromRot() { - IRunningObjectTable *pROT; - if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) { + CComPtr pROT; + + if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) pROT->Revoke(pdwRegister); - pROT->Release(); - } } #endif // #if EXPORT_GRAPH @@ -133,182 +131,179 @@ RemoveFromRot(); #endif // #if EXPORT_GRAPH - free_interface(pMpeg2Data); + pMpeg2Data.Release(); - free_interface(pVMRControl); - free_interface(pGraph); + pVMRControl.Release(); + pGraph.Release(); - free_interface(pVideoCodec); - free_interface(pAudioCodec); - free_interface(pAc3Codec); + pVideoCodec.Release(); + pAudioCodec.Release(); + pAc3Codec.Release(); - free_interface(pMapMPEG2); - free_interface(pMapH264); - free_interface(pMapSound); - free_interface(pMapAc3); - free_interface(pMapPmt); + pMapMPEG2.Release(); + pMapH264.Release(); + pMapSound.Release(); + pMapAc3.Release(); + pMapPmt.Release(); - free_interface(pDemux); - free_interface(pVMR); - free_interface(pDSound); - free_interface(pDSoundAc3); + pDemux.Release(); + pVMR.Release(); + pDSound.Release(); + pDSoundAc3.Release(); - free_interface(pNetworkTuner); - free_interface(pReceiverComponent); + pNetworkTuner.Release(); + pReceiverComponent.Release(); - free_interface(pStats); - free_interface(pBDAFreq); - free_interface(pBDAControl); + pStats.Release(); + pBDAFreq.Release(); + pBDAControl.Release(); // Libère les interfaces d'enregistrements for (int i=0; i & pFilter) { - HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, - IID_IBaseFilter, (void**)&pFilter); + HRESULT hr = pFilter.CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER); - if (FAILED(hr)) { - erreur(L"Le filtre \"%s\" n'a pas pu être créé", hr, nom); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le filtre \"%s\" n'a pas pu être créé", hr, nom); hr = pGraph->AddFilter(pFilter, nom); - if (FAILED(hr)) { - pFilter->Release(); - erreur(L"Le filtre \"%s\" n'a pas pu être ajouté au graphe", hr, nom); - } + if (FAILED(hr)) + return erreur(L"Le filtre \"%s\" n'a pas pu être ajouté au graphe", hr, nom); return hr; } -static HRESULT connect_filters(IBaseFilter * source, IBaseFilter * dest) +static HRESULT connect_filters(CComPtr & source, CComPtr & dest) { - IPin * pPin1 = NULL; - IPin * pPin2 = NULL; - HRESULT hr = cherche_pin(source, PINDIR_OUTPUT, pPin1); + CComPtr pPin1; + CComPtr pPin2; + HRESULT hr = cherche_pin(source, PINDIR_OUTPUT, pPin1); - if (SUCCEEDED(hr) && pPin1!=NULL) { + if (SUCCEEDED(hr)) { hr = cherche_pin(dest, PINDIR_INPUT, pPin2); - if (SUCCEEDED(hr) && pPin2!=NULL) { + if (SUCCEEDED(hr)) hr = pGraph->ConnectDirect(pPin1, pPin2, NULL); - pPin2->Release(); - } - pPin1->Release(); } return hr; } -static HRESULT getFrequencyFilter(IBaseFilter * pNetworkTuner) +static HRESULT getFrequencyFilter(CComPtr & pNetworkTuner) { - HRESULT hr = pNetworkTuner->QueryInterface(&pBDAControl); - if (FAILED(hr)) { - erreur(L"L'interface IBDA_DeviceControl n'a pas été trouvée", hr); - return hr; - } + HRESULT hr = pNetworkTuner.QueryInterface(&pBDAControl); - IBDA_Topology * pTop; - hr = pNetworkTuner->QueryInterface(&pTop); - if (FAILED(hr)) { - erreur(L"L'interface IBDA_Topology n'a pas été trouvée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"L'interface IBDA_DeviceControl n'a pas été trouvée", hr); + CComQIPtr pTop(pNetworkTuner); + + if (!pTop) + return erreur(L"L'interface IBDA_Topology n'a pas été trouvée", E_NOINTERFACE); + ULONG NodeTypes; ULONG NodeType[32]; - hr = pTop->GetNodeTypes(&NodeTypes, 32, NodeType); + hr = pTop->GetNodeTypes(&NodeTypes, _countof(NodeType), NodeType); - if (hr == S_OK) { - for (ULONG i = 0; i < NodeTypes && pBDAFreq == NULL; i++) { - ULONG Interfaces; - GUID Interface[32]; + if (FAILED(hr)) + return hr; - hr = pTop->GetNodeInterfaces(NodeType[i], &Interfaces, 32, Interface); + for (ULONG i = 0; i < NodeTypes && !pBDAFreq; i++) { + ULONG Interfaces; + GUID Interface[32]; - if (hr == S_OK) { + hr = pTop->GetNodeInterfaces(NodeType[i], &Interfaces, _countof(Interface), Interface); - bool found = false; + if (FAILED(hr)) + continue; - for (ULONG j = 0; j < Interfaces; j++) { - if (Interface[j] == IID_IBDA_FrequencyFilter) { - found = true; - } - } + bool found = false; - if (found) { - IUnknown * pUnk; - hr = pTop->GetControlNode(0, 1, NodeType[i], &pUnk); - if (SUCCEEDED(hr)) { - hr = pUnk->QueryInterface(&pBDAFreq); - pUnk->Release(); - } - } + for (ULONG j = 0; j < Interfaces; j++) { + if (Interface[j] == IID_IBDA_FrequencyFilter) { + found = true; + break; } } + + if (found) { + CComPtr pUnk; + + hr = pTop->GetControlNode(0, 1, NodeType[i], &pUnk); + if (SUCCEEDED(hr)) { + hr = pUnk.QueryInterface(&pBDAFreq); + break; + } + } } - pTop->Release(); - return hr; + return !pBDAFreq ? E_NOINTERFACE : hr; } -static HRESULT getSignalStatistics(IBaseFilter * pNetworkTuner) +static HRESULT getSignalStatistics(CComPtr & pNetworkTuner) { + CComQIPtr pTop(pNetworkTuner); - IBDA_Topology * pTop; - HRESULT hr = pNetworkTuner->QueryInterface(&pTop); - if (FAILED(hr)) { - erreur(L"L'interface IBDA_Topology n'a pas été trouvée", hr); - return hr; - } + if (!pTop) + return erreur(L"L'interface IBDA_Topology n'a pas été trouvée", E_NOINTERFACE); ULONG NodeTypes; ULONG NodeType[32]; - hr = pTop->GetNodeTypes(&NodeTypes, 32, NodeType); + HRESULT hr = pTop->GetNodeTypes(&NodeTypes, _countof(NodeType), NodeType); - if (hr == S_OK) { - for (ULONG i = 0; i < NodeTypes && pStats == NULL; i++) { - ULONG Interfaces; - GUID Interface[32]; + if (FAILED(hr)) + return hr; - hr = pTop->GetNodeInterfaces(NodeType[i], &Interfaces, 32, Interface); + for (ULONG i = 0; i < NodeTypes && !pStats; i++) { + ULONG Interfaces; + GUID Interface[32]; - if (hr == S_OK) { - bool found = false; + hr = pTop->GetNodeInterfaces(NodeType[i], &Interfaces, _countof(Interface), Interface); - for (ULONG j = 0; j < Interfaces; j++) { - if (Interface[j] == IID_IBDA_SignalStatistics ) { - found = true; - } - } + if (FAILED(hr)) + continue; - if (found) { - IUnknown * pUnk; - hr = pTop->GetControlNode(0, 1, NodeType[i], &pUnk); - if (SUCCEEDED(hr)) { - hr = pUnk->QueryInterface(&pStats); - pUnk->Release(); - } - } + bool found = false; + + for (ULONG j = 0; j < Interfaces; j++) { + if (Interface[j] == IID_IBDA_SignalStatistics) { + found = true; + break; } } + + if (found) { + CComPtr pUnk; + + hr = pTop->GetControlNode(0, 1, NodeType[i], &pUnk); + if (SUCCEEDED(hr)) { + hr = pUnk.QueryInterface(&pStats); + break; + } + } } - pTop->Release(); - return hr; + return !pStats ? E_NOINTERFACE : hr; } static HRESULT render_mp2v(IMpeg2Demultiplexer * pMpeg2Demux) { - IPin * pVideoPin; + if (filtreMPEG2[0] == 0) { + affiche_erreurs(L"Aucun codec vidéo MPEG2 n'a été sélectionné"); + return S_OK; + } + CComPtr pVideoPin; + AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_Video; am.subtype = MEDIASUBTYPE_MPEG2_VIDEO; @@ -341,10 +336,8 @@ mvi.hdr.bmiHeader.biHeight = 576; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"video", &pVideoPin); - if (FAILED(hr)) { - erreur(L"La broche vidéo MPEG2 n'a pas pu être créée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"La broche vidéo MPEG2 n'a pas pu être créée", hr); // le décodeur vidéo hr = get_filter(MEDIATYPE_Video, MEDIASUBTYPE_MPEG2_VIDEO, filtreMPEG2, pVideoCodec); @@ -352,33 +345,24 @@ myprintf(L"Ajout video MPEG2\n"); hr = pGraph->AddFilter(pVideoCodec, filtreMPEG2); - if (FAILED(hr)) { - erreur(L"Le codec vidéo MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreMPEG2); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le codec vidéo MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreMPEG2); - IPin * pPinEntree = NULL; + CComPtr pPinEntree; hr = cherche_pin(pVideoCodec, PINDIR_INPUT, pPinEntree); - if (SUCCEEDED(hr) && pPinEntree!=NULL) { + if (SUCCEEDED(hr)) hr = pGraph->ConnectDirect(pVideoPin, pPinEntree, NULL); - pPinEntree->Release(); - } - if (FAILED(hr)) { - erreur(L"Impossible de connecter le démultiplexeur au codec vidéo MPEG2 \"%s\"", hr, filtreMPEG2); - return hr; - } + if (FAILED(hr)) + return erreur(L"Impossible de connecter le démultiplexeur au codec vidéo MPEG2 \"%s\"", hr, filtreMPEG2); } else { hr = pGraph->RenderEx(pVideoPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); - if (FAILED(hr)) { - erreur(L"Pas de rendu possible depuis la broche vidéo MPEG2", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Pas de rendu possible depuis la broche vidéo MPEG2", hr); } - pVideoPin->QueryInterface(&pMapMPEG2); - pVideoPin->Release(); + pVideoPin.QueryInterface(&pMapMPEG2); return hr; } @@ -397,13 +381,11 @@ return hr; { - MyV(IVMRFilterConfig) * pVMRConfig; - hr = pVMR->QueryInterface(&pVMRConfig); - if (FAILED(hr)) { - erreur(L"L'interface de configuration VMR n'est pas disponible", hr); - return hr; - } + CComQIPtr pVMRConfig(pVMR); + if (!pVMRConfig) + return erreur(L"L'interface de configuration VMR n'est pas disponible", E_NOINTERFACE); + #if USE_VMR9 hr = pVMRConfig->SetRenderingMode(MyVMRMode_Windowless); #else @@ -412,80 +394,62 @@ if (SUCCEEDED(hr) && use_vmr_deinterlace) hr = pVMRConfig->SetNumberOfStreams(1); #endif - - pVMRConfig->Release(); - if (FAILED(hr)) - return hr; } + if (FAILED(hr)) + return hr; + #if !USE_VMR9 // Modif R_One - à revérifier { - MyV(IVMRSurfaceAllocatorNotify) * pNotify; - hr = pVMR->QueryInterface(&pNotify); - if (FAILED(hr)) { - erreur(L"L'interface IVMRSurfaceAllocatorNotify n'a pas été trouvée", hr); - return hr; - } + CComQIPtr pNotify(pVMR); - MyV(IVMRSurfaceAllocator) * pSurfAlloc = NULL; + if (!pNotify) + return erreur(L"L'interface IVMRSurfaceAllocatorNotify n'a pas été trouvée", E_NOINTERFACE); - hr = CoCreateInstance( CLSID_AllocPresenter, NULL, - CLSCTX_INPROC_SERVER, - MyV(IID_IVMRSurfaceAllocator), - (LPVOID*)&pSurfAlloc); + CComPtr pSurfAlloc; - if (FAILED(hr)) { - erreur(L"L'interface IVMRSurfaceAllocator n'a pas été trouvée", hr); - return hr; - } + hr = pSurfAlloc.CoCreateInstance(CLSID_AllocPresenter, NULL, CLSCTX_INPROC_SERVER); - MyV(IVMRImagePresenterConfig) * pPresConf = NULL; + if (FAILED(hr)) + return erreur(L"L'interface IVMRSurfaceAllocator n'a pas été trouvée", hr); - hr = pSurfAlloc->QueryInterface(&pPresConf); - if (FAILED(hr)) { - erreur(L"L'interface IVMRImagePresenterConfig n'a pas été trouvée", hr); - return hr; - } + { + CComQIPtr pPresConf(pSurfAlloc); - if (is_vista) { - hr = pPresConf->SetRenderingPrefs(RenderPrefs_AllowOffscreen); - } else { - hr = pPresConf->SetRenderingPrefs(RenderPrefs_ForceOverlays | RenderPrefs_DoNotRenderColorKeyAndBorder); + if (!pPresConf) + return erreur(L"L'interface IVMRImagePresenterConfig n'a pas été trouvée", E_NOINTERFACE); + + hr = pPresConf->SetRenderingPrefs( + is_vista ? + RenderPrefs_AllowOffscreen : + (RenderPrefs_ForceOverlays | RenderPrefs_DoNotRenderColorKeyAndBorder) + ); + + if (FAILED(hr)) + return erreur(L"Échec de SetRenderingPrefs", hr); } - pPresConf->Release(); - if (FAILED(hr)) { - erreur(L"Échec de SetRenderingPrefs", hr); - return hr; - } pNotify->AdviseSurfaceAllocator(0x118218, pSurfAlloc); pSurfAlloc->AdviseNotify(pNotify); } if (use_vmr_deinterlace) { + { + CComQIPtr pMixControl(pVMR); - MyV(IVMRMixerControl) * pMixControl; - - hr = pVMR->QueryInterface(&pMixControl); - if (FAILED(hr)) { - erreur(L"L'interface IVMRMixerControl n'a pas été trouvée", hr); - return hr; + if (!pMixControl) + return erreur(L"L'interface IVMRMixerControl n'a pas été trouvée", E_NOINTERFACE); + hr = pMixControl->SetMixingPrefs(MyMIXINGPREFS); } - hr = pMixControl->SetMixingPrefs(MyMIXINGPREFS); - pMixControl->Release(); - if (FAILED(hr)) { - erreur(L"Échec de SetMixingPrefs", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Échec de SetMixingPrefs", hr); - MyV(IVMRDeinterlaceControl) * pDeint; - hr = pVMR->QueryInterface(&pDeint); - if (FAILED(hr)) { - erreur(L"L'interface IVMRDeinterlaceControl n'a pas été trouvée", hr); - return hr; - } + CComQIPtr pDeint(pVMR); + if (!pDeint) + return erreur(L"L'interface IVMRDeinterlaceControl n'a pas été trouvée", E_NOINTERFACE); + DWORD num; MyVMRVideoDesc desc; @@ -507,10 +471,8 @@ hr = pDeint->GetNumberOfDeinterlaceModes(&desc, &num, NULL); - if (FAILED(hr)) { - erreur(L"Nombre de modes de désentrelacement non trouvé", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Nombre de modes de désentrelacement non trouvé", hr); myprintf(L"num : %i\n", num); @@ -519,23 +481,18 @@ hr = pDeint->GetNumberOfDeinterlaceModes(&desc, &num, guid); - if (FAILED(hr)) { - erreur(L"Impossible d'avoir le GUID du désentrelacement", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Impossible d'avoir le GUID du désentrelacement", hr); hr = pDeint->SetDeinterlaceMode(0xFFFFFFFF, &guid[0]); - pDeint->Release(); - if (FAILED(hr)) { - erreur(L"Impossible de mettre le mode de désentrelacement", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Impossible de mettre le mode de désentrelacement", hr); } #endif // #if !USE_VMR9 - hr = pVMR->QueryInterface(&pVMRControl); + hr = pVMR.QueryInterface(&pVMRControl); if (FAILED(hr)) { erreur(L"L'interface de contrôle VMR n'est pas disponible", hr); return hr; @@ -548,16 +505,11 @@ #endif { - MyV(IVMRAspectRatioControl) * pARC; - hr = pVMR->QueryInterface(&pARC); + CComQIPtr pARC(pVMR); - if (FAILED(hr)) { - erreur(L"L'interface de contrôle du ratio d'aspect n'est pas disponible", hr); - return hr; - } - + if (!pARC) + return erreur(L"L'interface de contrôle du ratio d'aspect n'est pas disponible", E_NOINTERFACE); pARC->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX); - pARC->Release(); } @@ -580,7 +532,7 @@ static HRESULT render_son(IMpeg2Demultiplexer * pMpeg2Demux) { - IPin * pSoundPin; + CComPtr pSoundPin; AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_Audio; @@ -605,10 +557,8 @@ wfm.cbSize = 0; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"son", &pSoundPin); - if (FAILED(hr)) { - erreur(L"La broche audio MPEG2 n'a pas pu être créée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"La broche audio MPEG2 n'a pas pu être créée", hr); // add direct sound hr = create_and_add_filter(CLSID_DSoundRender, L"DirectSound (MPEG2)", pDSound); @@ -623,48 +573,37 @@ hr = pGraph->AddFilter(pAudioCodec, filtreAudio); - if (FAILED(hr)) { - erreur(L"Le codec audio MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAudio); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le codec audio MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAudio); - IPin * pPinEntree = NULL; + CComPtr pPinEntree; hr = cherche_pin(pAudioCodec, PINDIR_INPUT, pPinEntree); - if (SUCCEEDED(hr) && pPinEntree != NULL) { + if (SUCCEEDED(hr)) hr = pGraph->ConnectDirect(pSoundPin, pPinEntree, NULL); - pPinEntree->Release(); - } - if (FAILED(hr)) { - erreur(L"Impossible de connecter le démultiplexeur au codec audio MPEG2 \"%s\"", hr, filtreAudio); - return hr; - } + if (FAILED(hr)) + return erreur(L"Impossible de connecter le démultiplexeur au codec audio MPEG2 \"%s\"", hr, filtreAudio); hr = connect_filters(pAudioCodec, pDSound); - if (FAILED(hr)) { - erreur(L"Impossible de connecter le Codec audio MPEG2 \"%s\" au filtre de rendu DirectSound", hr, filtreAudio); - return hr; - } + if (FAILED(hr)) + return erreur(L"Impossible de connecter le Codec audio MPEG2 \"%s\" au filtre de rendu DirectSound", hr, filtreAudio); } else { hr = pGraph->RenderEx(pSoundPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); - if (FAILED(hr)) { - erreur(L"Pas de rendu possible depuis la broche audio MPEG2", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Pas de rendu possible depuis la broche audio MPEG2", hr); } - hr = pSoundPin->QueryInterface(&pMapSound); + hr = pSoundPin.QueryInterface(&pMapSound); myprintf(L"%?erreur pMapSound, hr=0x%08x\n", FAILED(hr), hr); - pSoundPin->Release(); return hr; } static HRESULT render_ac3(IMpeg2Demultiplexer * pMpeg2Demux) { - IPin * pAc3Pin; + CComPtr pAc3Pin; AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_Audio; @@ -690,10 +629,8 @@ HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"ac3", &pAc3Pin); - if (FAILED(hr)) { - erreur(L"La broche audio AC3 n'a pas pu être créée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"La broche audio AC3 n'a pas pu être créée", hr); // add direct sound hr = create_and_add_filter(CLSID_DSoundRender, L"DirectSound (AC3)", pDSoundAc3); @@ -708,41 +645,30 @@ hr = pGraph->AddFilter(pAc3Codec, filtreAc3); - if (FAILED(hr)) { - erreur(L"Le codec audio AC3 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAc3); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le codec audio AC3 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAc3); - IPin * pPinEntree = NULL; + CComPtr pPinEntree; hr = cherche_pin(pAc3Codec, PINDIR_INPUT, pPinEntree); - if (SUCCEEDED(hr) && pPinEntree!=NULL) { + if (SUCCEEDED(hr)) hr = pGraph->ConnectDirect(pAc3Pin, pPinEntree, NULL); - pPinEntree->Release(); - } - if (FAILED(hr)) { - erreur(L"Impossible de connecter le démultiplexeur au codec AC3 \"%s\"", hr, filtreAc3); - return hr; - } + if (FAILED(hr)) + return erreur(L"Impossible de connecter le démultiplexeur au codec AC3 \"%s\"", hr, filtreAc3); hr = connect_filters(pAc3Codec, pDSoundAc3); - if (FAILED(hr)) { - erreur(L"Impossible de connecter le Codec audio AC3 \"%s\" au filtre de rendu DirectSound", hr, filtreAc3); - return hr; - } + if (FAILED(hr)) + return erreur(L"Impossible de connecter le Codec audio AC3 \"%s\" au filtre de rendu DirectSound", hr, filtreAc3); } else { hr = pGraph->RenderEx(pAc3Pin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); - if (FAILED(hr)) { - erreur(L"Pas de rendu possible depuis la broche audio AC3", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Pas de rendu possible depuis la broche audio AC3", hr); } - hr = pAc3Pin->QueryInterface(&pMapAc3); + hr = pAc3Pin.QueryInterface(&pMapAc3); myprintf(L"%?erreur pMapAc3, hr=0x%08x\n", FAILED(hr), hr); - pAc3Pin->Release(); return hr; } @@ -750,7 +676,7 @@ static HRESULT render_psi(IMpeg2Demultiplexer * pMpeg2Demux) { - IPin * pDataPin; + CComPtr pDataPin; AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_MPEG2_SECTIONS; @@ -772,45 +698,37 @@ // add mpeg2 { - IBaseFilter * pMpeg2Filter = NULL; + CComPtr pPSIFilter; - hr = create_and_add_filter(__uuidof(Mpeg2Data), L"MPEG-2 Sections and Tables", pMpeg2Filter); + hr = create_and_add_filter(__uuidof(Mpeg2Data), L"MPEG-2 Sections and Tables", pPSIFilter); if (FAILED(hr)) return hr; // query MPEG-2 Sections and Tables Filter - hr = pMpeg2Filter->QueryInterface(&pMpeg2Data); + hr = pPSIFilter.QueryInterface(&pMpeg2Data); if (FAILED(hr)) { erreur(L"L'interface d'accès aux tables PSI n'a pas été trouvée", hr); return hr; } - IPin * pPinEntree = NULL; + CComPtr pPinEntree; - hr = cherche_pin(pMpeg2Filter, PINDIR_INPUT, pPinEntree); - if (SUCCEEDED(hr) && pPinEntree!=NULL) { + hr = cherche_pin(pPSIFilter, PINDIR_INPUT, pPinEntree); + if (SUCCEEDED(hr)) hr = pGraph->ConnectDirect(pDataPin, pPinEntree, NULL); - pPinEntree->Release(); - } - if (FAILED(hr)) { - erreur(L"Impossible de connecter le démultiplexeur au filtre PSI", hr); - return hr; - } - - pMpeg2Filter->Release(); + if (FAILED(hr)) + return erreur(L"Impossible de connecter le démultiplexeur au filtre PSI", hr); } - pDataPin->Release(); - return hr; } static HRESULT render_epgfilter(IMpeg2Demultiplexer * pMpeg2Demux) { - IPin * pEpgPin; + CComPtr pEpgPin; AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_MPEG2_SECTIONS; @@ -832,52 +750,41 @@ // add mpeg2 { - CEPGFilter * pEPGFilter = + CComPtr pEPGFilter = dynamic_cast (CEPGFilter::CreateInstance(NULL, &hr)); - if (FAILED(hr)) { - erreur(L"Le filtre EPG n'a pas pu être créé", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le filtre EPG n'a pas pu être créé", hr); hr = pGraph->AddFilter(pEPGFilter, CEPGFilter::szFilterName); - if (FAILED(hr)) { - erreur(L"Le filtre EPG n'a pas pu être ajouté au graphe", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le filtre EPG n'a pas pu être ajouté au graphe", hr); - IPin * pPinEntree = NULL; + CComPtr pPinEntree; hr = cherche_pin(pEPGFilter, PINDIR_INPUT, pPinEntree); - if (FAILED(hr) || pEPGFilter == NULL) { - erreur(L"La broche d'entrée EPG n'a pas été trouvée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"La broche d'entrée EPG n'a pas été trouvée", hr); hr = pGraph->ConnectDirect(pEpgPin, pPinEntree, NULL); - pPinEntree->Release(); - if (FAILED(hr)) { - erreur(L"La broche d'entrée EPG n'a pas pu être connectée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"La broche d'entrée EPG n'a pas pu être connectée", hr); } - IMPEG2PIDMap * pMapEpg; - hr = pEpgPin->QueryInterface(&pMapEpg); - if (SUCCEEDED(hr)) { - ULONG pid = p_pid_EIT; + CComQIPtr pMapEpg(pEpgPin); - pMapEpg->MapPID(1, &pid, MEDIA_MPEG2_PSI); - pMapEpg->Release(); - } - pEpgPin->Release(); + if (!pMapEpg) + return E_NOINTERFACE; + ULONG pid = p_pid_EIT; + + pMapEpg->MapPID(1, &pid, MEDIA_MPEG2_PSI); return hr; } static HRESULT render_pmtfilter(IMpeg2Demultiplexer * pMpeg2Demux) { - IPin * pPmtPin; + CComPtr pPmtPin; AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_MPEG2_SECTIONS; @@ -892,119 +799,85 @@ am.pbFormat = NULL; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"pmt", &pPmtPin); - if (FAILED(hr)) { - erreur(L"La broche PMT n'a pas pu être créée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"La broche PMT n'a pas pu être créée", hr); + // add mpeg2 { - // CLSID clsid = {6, 7, 8, 9, 10, 11, 12, 13, 14}; - CPMTFilter * pPMTFilter = + CComPtr pPMTFilter = dynamic_cast(CPMTFilter::CreateInstance(NULL, &hr)); // new CPMTFilter(clsid, &hr); - if (FAILED(hr)) { - erreur(L"Le filtre PMT n'a pas pu être créé", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le filtre PMT n'a pas pu être créé", hr); hr = pGraph->AddFilter(pPMTFilter, CPMTFilter::szFilterName); - if (FAILED(hr)) { - erreur(L"Le filtre PMT n'a pas pu être ajouté au graphe", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le filtre PMT n'a pas pu être ajouté au graphe", hr); - IPin * pPinEntree = NULL; + CComPtr pPinEntree; hr = cherche_pin(pPMTFilter, PINDIR_INPUT, pPinEntree); - if (FAILED(hr) || pPMTFilter == NULL) - { - erreur(L"La broche d'entrée PMT n'a pas été trouvée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"La broche d'entrée PMT n'a pas été trouvée", hr); hr = pGraph->ConnectDirect(pPmtPin, pPinEntree, NULL); - pPinEntree->Release(); - if (FAILED(hr)) { - erreur(L"La broche d'entrée PMT n'a pas pu être connectée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"La broche d'entrée PMT n'a pas pu être connectée", hr); } - hr = pPmtPin->QueryInterface(&pMapPmt); + hr = pPmtPin.QueryInterface(&pMapPmt); myprintf(L"%?erreur pMapPmt, hr=0x%08x\n", FAILED(hr), hr); - pPmtPin->Release(); - return hr; } static HRESULT cree_and_render_pins() { + // crée les ports - // cree les ports + CComQIPtr pMpeg2Demux(pDemux); + if (!pMpeg2Demux) + return erreur(L"L'interface du démultiplexeur n'a pas été trouvée", E_NOINTERFACE); + HRESULT hr; - IMpeg2Demultiplexer * pMpeg2Demux; - hr = pDemux->QueryInterface(&pMpeg2Demux); + if (FAILED(hr = render_mp2v(pMpeg2Demux))) + return erreur(L"Erreur lors du rendu de la broche vidéo MPEG2", hr); - if (FAILED(hr)) { - erreur(L"L'interface du démultiplexeur n'a pas été trouvée", hr); - return hr; - } + if (FAILED(hr = render_son(pMpeg2Demux))) + return erreur(L"Erreur lors du rendu de la broche audio MPEG2", hr); - if (FAILED(hr = render_mp2v(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu de la broche vidéo MPEG2", hr); - return hr; - } + if (FAILED(hr = render_ac3(pMpeg2Demux))) + return erreur(L"Erreur lors du rendu de la broche audio AC3", hr); - if (FAILED(hr = render_son(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu de la broche audio MPEG2", hr); - return hr; - } + if (FAILED(hr = render_psi(pMpeg2Demux))) + return erreur(L"Erreur lors du rendu de la broche PSI", hr); - if (FAILED(hr = render_ac3(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu de la broche audio AC3", hr); - return hr; - } + if (FAILED(hr = render_epgfilter(pMpeg2Demux))) + return erreur(L"Erreur lors du rendu de la broche EPG", hr); - if (FAILED(hr = render_psi(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu de la broche PSI", hr); - return hr; - } + if (FAILED(hr = render_pmtfilter(pMpeg2Demux))) + return erreur(L"Erreur lors du rendu de la broche PMT", hr); - if (FAILED(hr = render_epgfilter(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu de la broche EPG", hr); - return hr; - } - - if (FAILED(hr = render_pmtfilter(pMpeg2Demux))) { - erreur(L"Erreur lors du rendu de la broche PMT", hr); - return hr; - } - // fini - pMpeg2Demux->Release(); - return hr; } HRESULT build_graph(void) { int res; - // créer le graph + // créer le graphe - HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, - IID_IFilterGraph2, (void **)&pGraph); - if (FAILED(hr) ) { - erreur(L"Pas réussi à créer le graphe DirectShow !", hr); - return hr; - } + HRESULT hr = pGraph.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER); + if (FAILED(hr) ) + return erreur(L"Pas réussi à créer le graphe DirectShow !", hr); + // on logge #if LOG_DSHOW logFile = CreateFile(L"log_file.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); @@ -1015,15 +888,13 @@ #if EXPORT_GRAPH hr = AddToRot(); - if (FAILED(hr)) { - erreur(L"Échec de l'exportation du graphe", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Échec de l'exportation du graphe", hr); #endif // #if EXPORT_GRAPH { // filtre dvb-t - IBaseFilter * pNetworkProvider = + CComPtr pNetworkProvider = dynamic_cast(CNetworkProvider::CreateInstance(NULL, &hr)); if (SUCCEEDED(hr)) @@ -1033,12 +904,11 @@ return hr; } - IBaseFilter * pAvantDemux; + CComPtr pAvantDemux; res = filtre_compat(pNetworkTuner); if (res == 1) { - // PCI hr = pGraph->AddFilter(pNetworkTuner, nom_tuner); @@ -1068,55 +938,38 @@ } pAvantDemux = pReceiverComponent; - pAvantDemux->AddRef(); - } else if (res == 2) { - // USB // connect USB hr = pGraph->AddFilter(pNetworkTuner, nom_tuner); - if (FAILED(hr)) { - erreur(L"Échec de l'insertion du filtre Tuner USB", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Échec de l'insertion du filtre Tuner USB", hr); hr = connect_filters(pNetworkProvider, pNetworkTuner); - if (FAILED(hr)) { - erreur(L"Tuner USB non compatible, veuillez effacer \"config.ini\" et redémarrer", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Tuner USB non compatible, veuillez effacer \"config.ini\" et redémarrer", hr); pAvantDemux = pNetworkTuner; - pAvantDemux->AddRef(); - - - } else { + } else return E_FAIL; - } hr = getFrequencyFilter(pNetworkTuner); - if (FAILED(hr) || pBDAFreq == NULL) { - erreur(L"L'interface de changement de fréquence n'a pas été trouvée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"L'interface de changement de fréquence n'a pas été trouvée", hr); hr = getSignalStatistics(pNetworkTuner); - if (FAILED(hr) || pStats == NULL) { - erreur(L"L'interface de qualité du signal n'a pas été trouvée", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"L'interface de qualité du signal n'a pas été trouvée", hr); // ajoute pGrabber filter { // connect 3 - IBaseFilter *filtrePrec = pAvantDemux; - filtrePrec->AddRef(); - IBaseFilter * pGrabber; - + CComPtr filtrePrec = pAvantDemux; for (int i=0; i pGrabber; + wchar_t nom[20]; swprintf_s(nom, _countof(nom), L"Grabber %u", i); hr = create_and_add_filter(CLSID_SampleGrabber, nom, pGrabber); @@ -1124,12 +977,10 @@ return hr; hr = connect_filters(filtrePrec, pGrabber); - if (FAILED(hr)) { - erreur(L"Le grabber n'a pas pu être connecté à la carte TNT, veuillez effacer \"config.ini\" et redémarrer", hr); - return hr; - } + if (FAILED(hr)) + return erreur(L"Le grabber n'a pas pu être connecté à la carte TNT, veuillez effacer \"config.ini\" et redémarrer", hr); - filtrePrec->Release(); + filtrePrec.Release(); enregistrements_actuels[i].query(pGrabber); filtrePrec = pGrabber; } @@ -1140,16 +991,10 @@ if (FAILED(hr)) return hr; - hr = connect_filters(pGrabber, pDemux); - if (FAILED(hr)) { - erreur(L"Le grabber n'a pas pu être connecté au démultiplexeur, veuillez effacer \"config.ini\" et redémarrer", hr); - return hr; - } - - pGrabber->Release(); + hr = connect_filters(filtrePrec, pDemux); + if (FAILED(hr)) + return erreur(L"Le grabber n'a pas pu être connecté au démultiplexeur, veuillez effacer \"config.ini\" et redémarrer", hr); } - - pAvantDemux->Release(); } // fin des recherches, ajoute tout dans le graph @@ -1164,10 +1009,9 @@ // derniers trucs - hr = pGraph->QueryInterface(&pControl); - if (FAILED(hr)) { + hr = pGraph.QueryInterface(&pControl); + if (FAILED(hr)) return hr; - } hr = pControl->Run(); Modifié: trunk/graph.h =================================================================== --- trunk/graph.h 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/graph.h 2008-11-11 00:27:20 UTC (rev 139) @@ -29,38 +29,36 @@ #include -#define free_interface(X) if (X) { X->Release(); X=NULL;} - HRESULT build_graph(void); // retourne S_OK = pas d'erreur, != S_OK = erreur void clean_dshow(void); HRESULT init_vmr(void); -extern IMpeg2Data * pMpeg2Data; +extern CComPtr pMpeg2Data; -extern IFilterGraph2 * pGraph; +extern CComPtr pGraph; -extern IBaseFilter * pNetworkTuner; -extern IBaseFilter * pReceiverComponent; +extern CComPtr pNetworkTuner; +extern CComPtr pReceiverComponent; -extern MyV(IVMRWindowlessControl) * pVMRControl; +extern CComPtr pVMRControl; -extern IBDA_SignalStatistics * pStats; -extern IBDA_DeviceControl * pBDAControl; -extern IBDA_FrequencyFilter * pBDAFreq; +extern CComPtr pStats; +extern CComPtr pBDAControl; +extern CComPtr pBDAFreq; -extern IMPEG2PIDMap * pMapMPEG2; -extern IMPEG2PIDMap * pMapSound; -extern IMPEG2PIDMap * pMapAc3; -extern IMPEG2PIDMap * pMapPmt; +extern CComPtr pMapMPEG2; +extern CComPtr pMapSound; +extern CComPtr pMapAc3; +extern CComPtr pMapPmt; -extern IBaseFilter * pVMR; -extern IBaseFilter * pDSound; -extern IBaseFilter * pDSoundAc3; +extern CComPtr pVMR; +extern CComPtr pDSound; +extern CComPtr pDSoundAc3; -extern IBaseFilter * pVideoCodec; -extern IBaseFilter * pAudioCodec; -extern IBaseFilter * pAc3Codec; +extern CComPtr pVideoCodec; +extern CComPtr pAudioCodec; +extern CComPtr pAc3Codec; -extern IBaseFilter * pDemux; +extern CComPtr pDemux; extern bool use_vmr_deinterlace; Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/ini.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -286,7 +286,7 @@ HRESULT hr = xml.charge(fileName); - if (hr != S_OK) { + if (FAILED(hr)) { return 1; } @@ -458,7 +458,7 @@ HRESULT hr = xml.charge(fileName); - if (hr != S_OK) { + if (FAILED(hr)) { return 1; } @@ -845,7 +845,7 @@ **/ bool check_config(void) { - pNetworkTuner = get_tuner(KSCATEGORY_BDA_NETWORK_TUNER, nom_tuner); + get_tuner(KSCATEGORY_BDA_NETWORK_TUNER, nom_tuner, pNetworkTuner); if (pNetworkTuner == NULL) { return false; @@ -853,26 +853,19 @@ int res = filtre_compat(pNetworkTuner); if (res == 1) { // PCI - pReceiverComponent = get_tuner(KSCATEGORY_BDA_RECEIVER_COMPONENT, nom_receiver); + get_tuner(KSCATEGORY_BDA_RECEIVER_COMPONENT, nom_receiver, pReceiverComponent); if (filtre_compat(pReceiverComponent) != 0) { return true; } else { - pNetworkTuner->Release(); - pNetworkTuner = NULL; - - if (pReceiverComponent) { - pReceiverComponent->Release(); - pReceiverComponent = NULL; - } - + pNetworkTuner.Release(); + pReceiverComponent.Release(); return false; } } else if (res == 2) { // USB return true; } else { - pNetworkTuner->Release(); - pNetworkTuner = NULL; + pNetworkTuner.Release(); return false; } } Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/main.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -1199,28 +1199,26 @@ } } -static void create_property_dialog(IBaseFilter * pFilter, LPCOLESTR nom) +static void create_property_dialog(CComPtr & pFilter, LPCOLESTR nom) { - if (pFilter == NULL) { + if (!pFilter) { affiche_erreurs(L"Il faut d'abord configurer un filtre et redémarrer l'application"); return; } - ISpecifyPropertyPages * pPages; - HRESULT hr = pFilter->QueryInterface(&pPages); + CComQIPtr pPages(pFilter); - if (FAILED(hr)) { - affiche_erreurs(L"Ce filtre n'a pas de page de propriétés", hr); + if (!pPages) { + affiche_erreurs(L"Ce filtre n'a pas de page de propriétés", E_NOINTERFACE); return; } - IUnknown * pUnk; - hr = pPages->QueryInterface(&pUnk); + CComPtr pUnk(pPages); - if (SUCCEEDED(hr)) { + if (pUnk) { CAUUID caGUID; - hr = pPages->GetPages(&caGUID); + HRESULT hr = pPages->GetPages(&caGUID); if (SUCCEEDED(hr)) { LCID lcid = GetUserDefaultLCID(); @@ -1233,7 +1231,7 @@ 10, nom, 1, - &pUnk, + &pUnk.p, caGUID.cElems, caGUID.pElems, lcid, @@ -1247,11 +1245,7 @@ affiche_erreurs(L"Erreur lors de la création de la page de propriétés", hr); } } - - pUnk->Release(); } - pPages->Release(); - } static void traite_numero(int nb) @@ -1531,7 +1525,7 @@ LPWSTR wsVersion = new wchar_t[taille + 2]; swprintf_s(wsVersion, taille + 2, L"%S", versionInternet); CXMLWrapper xml; - if (xml.charge_xml(wsVersion) == S_OK) { + if (SUCCEEDED(xml.charge_xml(wsVersion))) { CXMLElement root = xml.getDocElement(); @@ -1664,16 +1658,14 @@ { POINT ar = {4, 3}; // (valeurs par défaut) - if (pVMR != NULL) { // pVMR pas toujours défini à cet endroit - IPin * pPin = NULL; - HRESULT hr = cherche_pin(pVMR, PINDIR_INPUT, pPin); + if (pVMR) { // pVMR pas toujours défini à cet endroit + CComPtr pPin; + HRESULT hr = cherche_pin(pVMR, PINDIR_INPUT, pPin); - if (SUCCEEDED(hr) && pPin != NULL) { + if (SUCCEEDED(hr)) { AM_MEDIA_TYPE am; hr = pPin->ConnectionMediaType(&am); - pPin->Release(); - if (SUCCEEDED(hr)) { VIDEOINFOHEADER2 * vih = (VIDEOINFOHEADER2 *)am.pbFormat; @@ -2713,7 +2705,7 @@ myprintf(L"Compile le : %S %S\n", __DATE__, __TIME__); myprintf(L"\tVista build: %d\n", VISTA + 0); - myprintf(L"Tuner : %s\nRécepteur : %s\nMPEG2 : %s\nAudio : %s\nAC3 : %s\nVille : %s\n", + myprintf(L"Tuner : %s\nRécepteur : %s\nMPEG2 : %s\nAudio : %s\nAC3 : %s\nVille : %s\n", nom_tuner, nom_receiver, filtreMPEG2, @@ -2880,8 +2872,12 @@ continue; } else if (FAILED(hr = InitDshow())) { clean_dshow(); - affiche_erreurs(L"Erreur lors de l'initialisation.\nVeuillez corriger la configuration.", hr); + affiche_erreurs(L"Erreur lors de l'initialisation.\nVeuillez corriger la configuration.", hr); config_ok = false; + + // Appeler une nouvelle fois, car certains filtres trouvent très malin d'appeler + // CoUninitialize pour se protéger des usages non autorisés : + CoInitializeEx(NULL,COINIT_MULTITHREADED); } } while (!config_ok); @@ -2931,7 +2927,7 @@ update_record_menus(hMainWnd); } } - + hMainMenu = GetMenu(hWnd); /** Modifié: trunk/network.cpp =================================================================== --- trunk/network.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/network.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -1,24 +1,24 @@ -/* - * network.cpp - * Copyright (C) 2006 Pouchin - * - * This file is part of Pouchin TV, a free DVB-T viewer. - * See http://pouchinteve.free.fr/ for updates. - * - * Pouchin TV is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Pouchin TV is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ +/* + * network.cpp + * Copyright (C) 2006 Pouchin + * + * This file is part of Pouchin TV, a free DVB-T viewer. + * See http://pouchinteve.free.fr/ for updates. + * + * Pouchin TV is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pouchin TV is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #include "network.h" #include "base.h" @@ -39,7 +39,8 @@ HRESULT CPinBidon::CheckMediaType(const CMediaType *pmt) { // myprintf(L"CheckMediaType\n"); - if ( *pmt->Type() == KSDATAFORMAT_TYPE_BDA_ANTENNA) return S_OK; + if (*pmt->Type() == KSDATAFORMAT_TYPE_BDA_ANTENNA) + return S_OK; return S_FALSE; } @@ -83,7 +84,7 @@ *phr = S_OK; myprintf(TEXT("%s construit\n"), szFilterName); } - } + } } CNetworkProvider::~CNetworkProvider() @@ -99,7 +100,7 @@ CNetworkProvider *pNewFilter = new CNetworkProvider(pUnk, phr); if (phr) { - if (pNewFilter == NULL) + if (pNewFilter == NULL) *phr = E_OUTOFMEMORY; else *phr = S_OK; Modifié: trunk/pmtfilter.cpp =================================================================== --- trunk/pmtfilter.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/pmtfilter.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -97,7 +97,8 @@ HRESULT CPMTFilter::CheckMediaType(const CMediaType * pmt) { - if ( *pmt->Type() == MEDIATYPE_MPEG2_SECTIONS) return S_OK; + if ( *pmt->Type() == MEDIATYPE_MPEG2_SECTIONS) + return S_OK; return S_FALSE; } Modifié: trunk/record.cpp =================================================================== --- trunk/record.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/record.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -105,19 +105,17 @@ return after; } -void Enregistrement::query(IBaseFilter * pGrabber) +void Enregistrement::query(CComPtr & pGrabber) { - - - if (pSample==NULL) { - HRESULT hr = pGrabber->QueryInterface(&pSample); + if (!pSample) { + HRESULT hr = pGrabber.QueryInterface(&pSample); myprintf(L"%?erreur query pSample, hr=0x%08x\n", FAILED(hr), hr); } } -void Enregistrement::free() +void Enregistrement::release() { - free_interface(pSample); + pSample.Release(); } /** Modifié: trunk/record.h =================================================================== --- trunk/record.h 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/record.h 2008-11-11 00:27:20 UTC (rev 139) @@ -42,10 +42,10 @@ class Enregistrement : public RecordInfo { public: - ISampleGrabber * pSample; + CComPtr pSample; // // Mini-constructeur : - Enregistrement() : pSample(NULL) {} + Enregistrement() {} // bool recording() const {return sidChaine >0;} bool isChannel(WORD sidCh) const {return sidChaine == sidCh;} @@ -55,8 +55,8 @@ // Prise en compte d'une programmation affectant une chaîne déjà en cours d'enregistrement bool modify_prog(Programme * pProg); - void query(IBaseFilter * pGrabber); - void free(); + void query(CComPtr & pGrabber); + void release(); // Calcul du temps restant avant fin enregistrement en millisecondes. // L'heure de référence (en principe l'heure système) doit être passée en paramètre. Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/recprog.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -302,9 +302,10 @@ // Ajout de cette programmation aux tâches programmées (retourne 'false' si échec) bool Programme::ajouterTacheProgrammee(LPCWSTR username, LPCWSTR motdepasse) const { - WCHAR taskName[_countof(nom)+4]; - ITaskScheduler * pITS; - SYSTEMTIME date = debut; + WCHAR taskName[_countof(nom)+4]; + SYSTEMTIME date = debut; + CComPtr pTask; + HRESULT hr; AddTime(date, -60*1000); // Soustraire 60 secondes @@ -312,19 +313,20 @@ genereNomTache(taskName, _countof(taskName)); // Accède au planificateur pour supprimer la tâche si elle existe - HRESULT hr = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void**)&pITS); - if (FAILED(hr)) { - myprintf(L"Erreur init task scheduler\n"); - return false; - } - // Supprime la tâche - hr = pITS->Delete(taskName); + { + CComPtr pITS; - // Crée la nouvelle tâche - ITask * pTask; + hr = pITS.CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER); + if (FAILED(hr)) { + myprintf(L"Erreur init task scheduler\n"); + return false; + } + // Supprime la tâche + pITS->Delete(taskName); - hr = pITS->NewWorkItem(taskName, CLSID_CTask, IID_ITask, (IUnknown**)&pTask); - pITS->Release(); + // Crée la nouvelle tâche + hr = pITS->NewWorkItem(taskName, CLSID_CTask, IID_ITask, (IUnknown**)&pTask); + } if (FAILED(hr)) { myprintf(L"Erreur création tâche %s\n", taskName); @@ -342,8 +344,8 @@ hr = pTask->SetAccountInformation(username, motdepasse); if (SUCCEEDED(hr)) { - WORD piNewTrigger; - ITaskTrigger * pTaskTrigger; + WORD piNewTrigger; + CComPtr pTaskTrigger; pTask->SetFlags(TASK_FLAG_DELETE_WHEN_DONE | TASK_FLAG_SYSTEM_REQUIRED); pTask->SetMaxRunTime(INFINITE); @@ -386,17 +388,11 @@ pTaskTrigger->SetTrigger(&Trig); - IPersistFile * pPersistFile; + CComQIPtr pPersistFile(pTask); - hr = pTask->QueryInterface(IID_IPersistFile, (void **)&pPersistFile); - if (SUCCEEDED(hr)) { + if (pPersistFile) pPersistFile->Save(NULL, TRUE); - pPersistFile->Release(); - } - - pTaskTrigger->Release(); } - pTask->Release(); return true; } @@ -437,12 +433,13 @@ bool Programme::supprimerTacheProgrammee() const { WCHAR taskName[_countof(nom)+4]; - ITaskScheduler * pITS; // On génère le nom de la tâche : genereNomTache(taskName, _countof(taskName)); - HRESULT hr = CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskScheduler, (void**)&pITS); + CComPtr pITS; + + HRESULT hr = pITS.CoCreateInstance(CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER); if (FAILED(hr)) { myprintf(L"Erreur init task scheduler\n"); return false; @@ -450,8 +447,6 @@ // Supprime la tâche pITS->Delete(taskName); - - pITS->Release(); return true; } @@ -567,7 +562,7 @@ **/ void set_timer_record() { - myprintf(L"Appel set_timer_record()\n"); + // myprintf(L"Appel set_timer_record()\n"); SYSTEMTIME localtime; long reste = DUREE_INFINIE; @@ -589,7 +584,7 @@ // Si l'heure de début est déjà passée, on lance un timer qui aboutit immédiatement long timer = min(max(reste, USER_TIMER_MINIMUM), DUREE_RECALCUL_TIMERS*1000); - myprintf(L"Temps avant événement enreg : %i mS, timer = %i mS\n", reste, timer); + // myprintf(L"Temps avant événement enreg : %i mS, timer = %i mS\n", reste, timer); SetTimer(hMainWnd, TIMER_DELAYED_RECORD, timer, NULL); } } @@ -1835,7 +1830,7 @@ **/ bool do_record_events() { - myprintf(L"Appel do_record_events()\n"); + // myprintf(L"Appel do_record_events()\n"); SYSTEMTIME localtime; Modifié: trunk/search.cpp =================================================================== --- trunk/search.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/search.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -62,20 +62,17 @@ **/ void search_filters(GUID type, GUID subtype, HWND hItm) { - IFilterMapper2 * pMapper; + CComPtr pMapper; - HRESULT hr = CoCreateInstance(CLSID_FilterMapper2, - NULL, CLSCTX_INPROC, IID_IFilterMapper2, (void **)&pMapper); + HRESULT hr = pMapper.CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC); if (FAILED(hr)) { myprintf(L"search_filters, 1, hr=0x%08x\n", hr); return; } - GUID arrayInTypes[2]; - arrayInTypes[0] = type; - arrayInTypes[1] = subtype; + GUID arrayInTypes[2] = {type, subtype}; - IEnumMoniker * pEnum; + CComPtr pEnum; hr = pMapper->EnumMatchingFilters( &pEnum, @@ -97,53 +94,47 @@ if (FAILED(hr)) { myprintf(L"search_filters, 2, hr=0x%08x\n", hr); - pMapper->Release(); return; } // Enumerate the monikers. - IMoniker *pMoniker; ULONG cFetched; - while (pEnum->Next(1, &pMoniker, &cFetched) == S_OK) { - IPropertyBag * pPropBag; - hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); - if (SUCCEEDED(hr)) { - // To retrieve the friendly name of the filter, do the following: - VARIANT varName; - VariantInit(&varName); - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if (SUCCEEDED(hr)) { - // Display the name in your UI somehow. - VarStr_helper vstr(varName); - //myprintf(L"filtre : %s\n", vstr); + for ( + CComPtr pMoniker; + pEnum->Next(1, &pMoniker, &cFetched)==S_OK; + pMoniker.Release() + ) { + CComPtr pPropBag; - SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)vstr()); - } - VariantClear(&varName); - pPropBag->Release(); - } - pMoniker->Release(); - } + if (FAILED(hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag))) + continue; - pEnum->Release(); + // To retrieve the friendly name of the filter, do the following: + CComVariant varName; - pMapper->Release(); + if (FAILED(hr = pPropBag->Read(L"FriendlyName", &varName, 0))) + continue; + // Display the name in your UI somehow. + VarStr_helper vstr(varName); + //myprintf(L"filtre : %s\n", vstr); + + SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)vstr()); + } } -HRESULT get_filter(GUID type, GUID subtype, LPCWSTR nom, IBaseFilter * & pFilter) +HRESULT get_filter(GUID type, GUID subtype, LPCWSTR nom, CComPtr & pFilter) { myprintf(L"get_filter: type={%08x-%04x-%04x-%012x}\n", type.Data1, type.Data2, type.Data3, type.Data4); myprintf(L"\tsubtype={%08x-%04x-%04x-%012x}\n", subtype.Data1, subtype.Data2, subtype.Data3, subtype.Data4); myprintf(L"\tnom=%s\n", nom); - IFilterMapper2 * pMapper; + pFilter.Release(); // au cas où - pFilter = NULL; + CComPtr pMapper; - HRESULT hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC, - IID_IFilterMapper2, (void **)&pMapper); + HRESULT hr = pMapper.CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC); if (FAILED(hr)) { myprintf(L"get_filter, 1, hr=0x%08x\n", hr); return hr; @@ -153,7 +144,7 @@ arrayInTypes[0] = type; arrayInTypes[1] = subtype; - IEnumMoniker * pEnum; + CComPtr pEnum; hr = pMapper->EnumMatchingFilters( &pEnum, @@ -174,129 +165,119 @@ if (FAILED(hr)) { myprintf(L"get_filter, 2, hr=0x%08x\n", hr); - pMapper->Release(); return hr; } // Enumerate the monikers. - IMoniker *pMoniker; ULONG cFetched; - while (pFilter == NULL && pEnum->Next(1, &pMoniker, &cFetched) == S_OK) { - IPropertyBag * pPropBag; + for ( + CComPtr pMoniker; + !pFilter && pEnum->Next(1, &pMoniker, &cFetched)==S_OK; + pMoniker.Release() + ) { + CComPtr pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); + if (FAILED(hr)) + continue; - if (SUCCEEDED(hr)) { - // To retrieve the friendly name of the filter, do the following: - VARIANT varName; - VariantInit(&varName); - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if (SUCCEEDED(hr)) { - // Display the name in your UI somehow. - VarStr_helper vstr(varName); + // To retrieve the friendly name of the filter, do the following: + CComVariant varName; - if (wcscmp(vstr(), nom)==0) { - hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); - } + if (FAILED(hr = pPropBag->Read(L"FriendlyName", &varName, 0))) + continue; + // Display the name in your UI somehow. + VarStr_helper vstr(varName); - } - VariantClear(&varName); - pPropBag->Release(); - } - pMoniker->Release(); + if (wcscmp(vstr(), nom)==0) + hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); } - pEnum->Release(); - pMapper->Release(); - return hr; } // 1er pin non connecté -HRESULT cherche_pin(IBaseFilter * pFilter, PIN_DIRECTION dir, IPin * & result) +HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, CComPtr & result) { - IEnumPins * pEnumPins; - HRESULT hr; - IPin * curpin = NULL; + CComPtr pEnumPins; + HRESULT hr = pFilter->EnumPins(&pEnumPins); - hr = pFilter->EnumPins(&pEnumPins); if (FAILED(hr)) { myprintf(L"cherche_pin, 1, hr=0x%08x\n", hr); return hr; } - while (pEnumPins->Next(1, &curpin, NULL)==S_OK ) { - + for ( + CComPtr curpin; + (hr = pEnumPins->Next(1, &curpin, NULL))==S_OK; + curpin.Release() + ) { PIN_DIRECTION direction; curpin->QueryDirection(&direction); if (direction == dir) { #ifdef _DEBUG - IPin * connected = NULL; + CComPtr connected; + curpin->ConnectedTo(&connected); - if (connected == NULL) { + if (!connected) { result = curpin; break; } - connected->Release(); #else result = curpin; break; #endif } - curpin->Release(); - curpin = NULL; } - pEnumPins->Release(); - - return S_OK; + return !result ? E_FAIL : hr; } // 0 pas compat, 1 tuner, 2 receiver -int filtre_compat(IBaseFilter * pFilter) +int filtre_compat(CComPtr & pFilter) { int res = 0; - if (pFilter == NULL) { + if (!pFilter) return res; - } - IEnumPins *pEnumPins; + CComPtr pEnumPins; + pFilter->EnumPins(&pEnumPins); - IPin *pPin; - while(pEnumPins->Next(1, &pPin, NULL) == S_OK && res == 0) { + for ( + CComPtr pPin; + res==0 && pEnumPins->Next(1, &pPin, NULL)==S_OK; + pPin.Release() + ) { PIN_DIRECTION dir; pPin->QueryDirection(&dir); - if (dir == PINDIR_OUTPUT) { + if (dir != PINDIR_OUTPUT) + continue; - IEnumMediaTypes * pEnumMedia; + CComPtr pEnumMedia; - pPin->EnumMediaTypes(&pEnumMedia); + pPin->EnumMediaTypes(&pEnumMedia); - AM_MEDIA_TYPE * am; + AM_MEDIA_TYPE * am; - while(pEnumMedia->Next(1, &am, NULL) == S_OK && res == 0) { - if (am->majortype == MEDIATYPE_Stream) { - - if (am->subtype == KSDATAFORMAT_TYPE_MPEG2_TRANSPORT) { - res = 1; - } else if (am->subtype == KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT) { - res = 2; - } - + while (res==0 && (pEnumMedia->Next(1, &am, NULL))==S_OK) { + if (am->majortype == MEDIATYPE_Stream) { + if (am->subtype == KSDATAFORMAT_TYPE_MPEG2_TRANSPORT) { + res = 1; + } else if (am->subtype == KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT) { + res = 2; } - - DeleteMediaType(am); } + + DeleteMediaType(am); } - pPin->Release(); } - pEnumPins->Release(); return res; } @@ -304,108 +285,94 @@ HRESULT remplit_tuners(GUID guid, HWND hItm) { // Create the System Device Enumerator. - ICreateDevEnum * pDevEnum; - HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, - IID_ICreateDevEnum, (void **)&pDevEnum); - if (FAILED(hr)) { - myprintf(L"remplit_tuners, ICreateDevEnum : hr=0x%08x\n", hr); + CComPtr pDevEnum; + + HRESULT hr = pDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER); + if (FAILED(hr)) return hr; - } - IEnumMoniker *pEnumMoniker = NULL; + CComPtr pEnumMoniker; hr = pDevEnum->CreateClassEnumerator(guid, &pEnumMoniker, 0); - if (FAILED(hr) || pEnumMoniker == NULL) { - myprintf(L"remplit_tuners, erreur création Enum Moniker : hr=0x%08x\n", hr); - pDevEnum->Release(); + if (FAILED(hr) || !pEnumMoniker) return hr; - } - IMoniker *pMoniker; - while (pEnumMoniker->Next(1, &pMoniker, NULL) == S_OK) { - IBaseFilter *pFilter; + for ( + CComPtr pMoniker; + pEnumMoniker->Next(1, &pMoniker, NULL)==S_OK; + pMoniker.Release() + ) { + CComPtr pFilter; HRESULT hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter); - if (SUCCEEDED(hr)) { - if (filtre_compat(pFilter)) { - IPropertyBag * pPropBag; - if (SUCCEEDED(pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag))) { - // To retrieve the friendly name of the filter, do the following: - VARIANT varName; - VariantInit(&varName); - if (SUCCEEDED(pPropBag->Read(L"FriendlyName", &varName, 0))) { - myprintf(L"remplit_tuner, Tuner : %s\n", varName.bstrVal); - SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)varName.bstrVal); - } - VariantClear(&varName); - pPropBag->Release(); - } + if (FAILED(hr) || filtre_compat(pFilter)==0) + continue; - } - pFilter->Release(); - } + CComPtr pPropBag; - pMoniker->Release(); - } + if (FAILED(pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag))) + continue; - pEnumMoniker->Release(); - pDevEnum->Release(); + // To retrieve the friendly name of the filter, do the following: + CComVariant varName; + if (SUCCEEDED(pPropBag->Read(L"FriendlyName", &varName, 0))) { + myprintf(L"remplit_tuner, Tuner : %s\n", varName.bstrVal); + SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)varName.bstrVal); + } + } + return hr; } // renvoie le filtre à partir du nom -IBaseFilter * get_tuner(GUID guid, wchar_t * nom) +HRESULT get_tuner(GUID guid, LPCWSTR nom, CComPtr & pFilter) { + pFilter.Release(); + myprintf(L"get_tuner: guid={%08x-%04x-%04x-%012x}, nom=%s\n", guid.Data1, guid.Data2, guid.Data3, guid.Data4, nom); + // Create the System Device Enumerator. - ICreateDevEnum * pDevEnum; - HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, - IID_ICreateDevEnum, (void **)&pDevEnum); + CComPtr pDevEnum; + + HRESULT hr = pDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER); + if (FAILED(hr)) { myprintf(L"get_tuner, ICreateDevEnum : hr=0x%08x\n", hr); - return NULL; + return hr; } - IEnumMoniker *pEnumMoniker = NULL; + CComPtr pEnumMoniker; hr = pDevEnum->CreateClassEnumerator(guid, &pEnumMoniker, 0); - if (FAILED(hr) || pEnumMoniker == NULL) { + if (FAILED(hr) || !pEnumMoniker) { myprintf(L"get_tuner, erreur création Enum Moniker : hr=0x%08x\n", hr); - pDevEnum->Release(); - return NULL; + return hr; } - IMoniker *pMoniker; - IBaseFilter * pFilter = NULL; + for ( + CComPtr pMoniker; + !pFilter && pEnumMoniker->Next(1, &pMoniker, NULL)==S_OK; + pMoniker.Release() + ) { + CComPtr pPropBag; - while (pEnumMoniker->Next(1, &pMoniker, NULL) == S_OK && pFilter == NULL) { - IPropertyBag * pPropBag; - if (SUCCEEDED(pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag))) { // To retrieve the friendly name of the filter, do the following: - VARIANT varName; - VariantInit(&varName); - if (SUCCEEDED(pPropBag->Read(L"FriendlyName", &varName, 0))) { - VarStr_helper vstr(varName); - myprintf(L"get_tuner, Tuner : %s\n", varName.bstrVal); - if (wcscmp(vstr(), nom)==0) { + CComVariant varName; - hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); - } + if (FAILED(pPropBag->Read(L"FriendlyName", &varName, 0))) + continue; - } - VariantClear(&varName); - pPropBag->Release(); - } + VarStr_helper vstr(varName); - pMoniker->Release(); + myprintf(L"get_tuner, Tuner : %s\n", varName.bstrVal); + if (wcscmp(vstr(), nom)==0) + hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); + } } - pEnumMoniker->Release(); - pDevEnum->Release(); - - return pFilter; + return hr; } Modifié: trunk/search.h =================================================================== --- trunk/search.h 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/search.h 2008-11-11 00:27:20 UTC (rev 139) @@ -29,12 +29,13 @@ //IBaseFilter * search_mpeg2(IEnumMoniker *pEnumMoniker, GUID subtype, GUID format); -HRESULT cherche_pin(IBaseFilter * pFilter, PIN_DIRECTION dir, IPin * & result); +HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, CComPtr & result); void search_filters(GUID type, GUID subtype, HWND hItm); -HRESULT get_filter(GUID type, GUID subtype, LPCWSTR nom, IBaseFilter * & pFilter); +HRESULT get_filter(GUID type, GUID subtype, LPCWSTR nom, CComPtr & pFilter); HRESULT remplit_tuners(GUID guid, HWND hItm); -IBaseFilter * get_tuner(GUID guid, wchar_t * nom); -int filtre_compat(IBaseFilter * pFilter); +HRESULT get_tuner(GUID guid, LPCWSTR nom, CComPtr & pFilter); +int filtre_compat(CComPtr & pFilter); + extern BOOL exact_match; Modifié: trunk/utils.h =================================================================== --- trunk/utils.h 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/utils.h 2008-11-11 00:27:20 UTC (rev 139) @@ -42,16 +42,17 @@ #include // Conversions 'printf' entre CHAR ou WCHAR vers TCHAR +// (3ème caractères en minuscules, sinon ça fait conflit avec certaines macros ATL) #ifdef _UNICODE - #define T2A "S" // TCHAR vers CHAR - #define T2W L"s" // TCHAR vers WCHAR - #define A2T L"S" // CHAR vers TCHAR - #define W2T L"s" // WCHAR vers TCHAR + #define T2a "S" // TCHAR vers CHAR + #define T2w L"s" // TCHAR vers WCHAR + #define A2t L"S" // CHAR vers TCHAR + #define W2t L"s" // WCHAR vers TCHAR #else - #define T2A "s" // TCHAR vers CHAR - #define T2W L"S" // TCHAR vers WCHAR - #define A2T "s" // CHAR vers TCHAR - #define W2T "S" // WCHAR vers TCHAR + #define T2a "s" // TCHAR vers CHAR + #define T2w L"S" // TCHAR vers WCHAR + #define A2t "s" // CHAR vers TCHAR + #define W2t "S" // WCHAR vers TCHAR #endif // Structure pour la sauvegarde de la position des fenêtres : Modifié: trunk/xml.cpp =================================================================== --- trunk/xml.cpp 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/xml.cpp 2008-11-11 00:27:20 UTC (rev 139) @@ -29,7 +29,8 @@ #include "xml.h" -CXMLElement::CXMLElement(IXMLDOMElement * element) : m_ele(element) +CXMLElement::CXMLElement(IXMLDOMElement * element) : + m_ele(element) { // myprintf(L"élément contruit\n"); } @@ -37,20 +38,17 @@ CXMLElement::~CXMLElement() { - m_ele->Release(); - // myprintf(L"élément détruit\n"); } std::vector CXMLElement::getChildren() { std::vector vect; + CComPtr pChildList; - IXMLDOMNodeList * pChildList = NULL; m_ele->get_childNodes(&pChildList); if (pChildList) { - long length; pChildList->get_length(&length); @@ -59,18 +57,15 @@ pChildList->get_item(i, &pNode); - vect.push_back(new CXMLNode(pNode)); } - - - pChildList->Release(); } return vect; } -CXMLNode::CXMLNode(IXMLDOMNode * element) : m_node(element) +CXMLNode::CXMLNode(IXMLDOMNode * element) : + m_node(element) { // myprintf(L"noeud construit\n"); } @@ -78,8 +73,6 @@ CXMLNode::~CXMLNode() { - m_node->Release(); - // myprintf(L"noeud détruit\n"); } @@ -87,7 +80,9 @@ { int rep = 0; bool trouve = false; - IXMLDOMNodeList * pChildList = NULL; + + CComPtr pChildList; + m_node->get_childNodes(&pChildList); if (pChildList) { @@ -96,7 +91,7 @@ pChildList->get_length(&length); for (long i=0; i pNode; pChildList->get_item(i, &pNode); BSTR bstr; @@ -112,9 +107,7 @@ } SysFreeString(bstr); - pNode->Release(); } - pChildList->Release(); } return rep; } @@ -122,16 +115,16 @@ void CXMLNode::getStr(const wchar_t * nom, wchar_t * str, size_t size) { bool found = false; - IXMLDOMNodeList * pChildList = NULL; + CComPtr pChildList; + m_node->get_childNodes(&pChildList); if (pChildList) { - long length; pChildList->get_length(&length); for (long i=0; i pNode; pChildList->get_item(i, &pNode); BSTR bstr; @@ -146,9 +139,7 @@ SysFreeString(txt); } SysFreeString(bstr); - pNode->Release(); } - pChildList->Release(); } } @@ -166,7 +157,8 @@ * Récupère des enfants à partir d'un nom **/ void CXMLNode::getChildrenByName(const wchar_t *nom, CXMLNode **noeud) { - IXMLDOMNodeList * pChildList = NULL; + CComPtr pChildList; + m_node->get_childNodes(&pChildList); bool found = false; @@ -177,7 +169,7 @@ pChildList->get_length(&length); for (long i=0; i pNode; pChildList->get_item(i, &pNode); @@ -189,23 +181,19 @@ if (wcscmp(bstr, nom) == 0 && bHasChild) { found = true; - IXMLDOMNode *node = NULL; + CComPtr node; + pNode->cloneNode(VARIANT_TRUE, &node); *noeud = new CXMLNode(node); } SysFreeString(bstr); - pNode->Release(); - } - pChildList->Release(); } - } CXMLWrapper::CXMLWrapper() { - CoCreateInstance(CLSID_DOMDocument, - NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&m_doc); + m_doc.CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER); // myprintf(L"wrapper contruit\n"); } @@ -213,26 +201,18 @@ CXMLWrapper::~CXMLWrapper() { - m_doc->Release(); - // myprintf(L"wrapper détruit\n"); } HRESULT CXMLWrapper::charge(const wchar_t * nom) { - VARIANT var; - VARIANT_BOOL status; + CComVariant var; + VARIANT_BOOL status; - VariantInit(&var); - var.vt = VT_BSTR; var.bstrVal = SysAllocString(nom); - HRESULT hr = m_doc->load(var, &status); - - VariantClear(&var); - - return hr; + return m_doc->load(var, &status); } /** @@ -270,7 +250,7 @@ CXMLElement CXMLWrapper::getDocElement() { - IXMLDOMElement * pDOMElement; + CComPtr pDOMElement; m_doc->get_documentElement(&pDOMElement); Modifié: trunk/xml.h =================================================================== --- trunk/xml.h 2008-11-09 22:21:51 UTC (rev 138) +++ trunk/xml.h 2008-11-11 00:27:20 UTC (rev 139) @@ -33,7 +33,7 @@ class CXMLNode { private: - IXMLDOMNode * m_node; + CComPtr m_node; public: CXMLNode(IXMLDOMNode * node); @@ -50,7 +50,7 @@ class CXMLElement { private: - IXMLDOMElement * m_ele; + CComPtr m_ele; public: CXMLElement(IXMLDOMElement * element); @@ -63,9 +63,7 @@ class CXMLWrapper { private: - IXMLDOMDocument * m_doc; - - + CComPtr m_doc; public: CXMLWrapper(); ~CXMLWrapper(); From pouchintv-dev at baysse.fr Tue Nov 11 14:47:23 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Tue, 11 Nov 2008 14:47:23 +0100 Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r139 - trunk In-Reply-To: <20081111002721.4B5485F331@mail.baysse.fr> References: <20081111002721.4B5485F331@mail.baysse.fr> Message-ID: <49198CEB.7030005@baysse.fr> Liste utilisée par les développeurs a écrit : > Author: gingko > Date: 2008-11-11 01:27:20 +0100 (mar, 11 nov 2008) > New Revision: 139 > > Modified: > trunk/LCD.cpp > trunk/base.cpp > trunk/base.h > trunk/channels.cpp > trunk/graph.cpp > trunk/graph.h > trunk/ini.cpp > trunk/main.cpp > trunk/network.cpp > trunk/pmtfilter.cpp > trunk/record.cpp > trunk/record.h > trunk/recprog.cpp > trunk/search.cpp > trunk/search.h > trunk/utils.h > trunk/xml.cpp > trunk/xml.h > Log: > Réécriture des déclarations d'instances d'objets issus des filtres DirectShow, > ainsi que d'autres objets dérivés du modèle d'objets COM, de manière à utiliser > les "smart pointers" définis dans la bibliothèques de modèles de classes > (templates) ATL. Ces classes gérant automatiquement les ajouts et suppressions > de références de ces objets (AddRef et Release), ceci permet de supprimer > la plupart de ces instructions, tout en s'assurant d'une gestion optimale > de ces objets avec réduction au minimum des risques de fuites de mémoires > et d'objets non détruits. > Ajout d'un nouvel appel redondant à "CoInitializeEx" en cas d'échec de > de la création du graphe, en raison du fait que certains filtres DirectShow > (Nero...) semblent s'autoprotéger contre les usages non autorisés en exécutant > une instruction "CoUninitialize", ce qui compliquait sérieusement le retour > subséquent au dialogue de configuration. > Optimisation supplémentaire de la gestion des messages d'erreurs (via ajout d'une > recopie du code d'erreur transmis à la fonction "erreur" vers la valeur de retour > de cette fonction). > Salut, je n'ai pas encore regardé les mais ta modification semble interdire l'utilisation de Visual Studio Express, car les ATL ne sont pas gérées par celui-ci Et de plus, est-ce que les ATL ne nécessitent pas des dépendances supplémentaires par rapport à un Windows de base ? -- lolo_32 From pouchintv-dev at baysse.fr Sun Nov 16 15:59:52 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Sun, 16 Nov 2008 15:59:52 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r140 - trunk Message-ID: <20081116145952.4649E5F3B7@mail.baysse.fr> Author: gingko Date: 2008-11-16 15:59:52 +0100 (dim, 16 nov 2008) New Revision: 140 Added: trunk/atlbase_ptvm.h Modified: trunk/Pouchin TV.vcproj trunk/base.cpp trunk/base.h Log: Ajout d'un jeu minimal de modèles de classes destinées à se substituer aux modèles de classes (templates) ATL que j'avais commencé à utiliser dans la précédente livraison. En effet, je me suis aperçu a posteriori que ces modèles de classes n'étaient disponibles que dans la version complète de Visual Studio 2005, et que sans ceux-ci, les utilisateurs de Visual C++ Express 2005 ne pouvaient plus compiler le programme. Les utilisateurs de Visual C++ Express 2005 peuvent utiliser ces définitions en activant la macro "DONT_HAVE_ATL_TEMPLATES" dans le fichier "base.h". Modification du projet principal pour référencer directement le dossier "BaseClasses" inclus : ainsi, il n'est plus nécessaire d'inclure ce dossier dans les répertoires d'inclusion globaux de l'environnement. Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2008-11-11 00:27:20 UTC (rev 139) +++ trunk/Pouchin TV.vcproj 2008-11-16 14:59:52 UTC (rev 140) @@ -53,12 +53,14 @@ UsePrecompiledHeader="0" WarningLevel="4" DebugInformationFormat="4" + DisableSpecificWarnings="4480" /> ), + * to use with a modified version of this software. + * See http://pouchinteve.free.fr/ for the original project. + */ + +#pragma once + +// Ce fichier contient des susbtituts minimaux aux modèles de classes +// (templates) ATL normalement inclus dans Visual Studio 2005 +// édition professionnelle, mais non fournis dans Visual C++ 2005 Express. + +// Ces modèles contiennent les fonctionnalités minimales nécessaires +// pour que le projet PouchinTV Mod puisse être compilé avec +// Visual C++ 2005 Express. + +// Les utilisateurs de Visual C++ 2005 Express qui désireraient cependant +// avoir un support plus complet de ces modèles de classes ATL peuvent +// télécharger et installer le Windows Server 2003 SP1 Device Driver Kit +// (nom du fichier = 1830_usa_ddk.iso) à l'adresse suivante : +// http://www.microsoft.com/whdc/devtools/ddk/ +// Il convient ensuite d'ajouter les répertoires suivants dans la liste des +// répertoires de VC++ : +// - Fichiers include : \inc\atl30 +// - Fichiers bibliothèques : \lib\atl\i386 +// est le répertoire d'installation du DDK +// (par défaut C:\WINDDK\3790.1830). + +template + class CComPtr +{ +public: + IU * p; + + CComPtr() : p(NULL) { + } + CComPtr(IU* q) : p(q) { + if (p) p->AddRef();} + CComPtr(const CComPtr & r) : p(r.p) { + if (p) p->AddRef();} + IU * operator -> () const { + return p;} + bool operator ! () const { + return p==NULL;} + IU** operator & () { + return &p;} + operator IU * () { + return p;} + void Release() { + IU* t=p; if (t) {p=NULL; t->Release();}} + IU* operator = (const IU* q) { + Release(); p=q; p->AddRef(); return p;} + CComPtr & operator = (const CComPtr & r) { + Release(); p=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) { + return ::CoCreateInstance(g, u, c, __uuidof(IU), (void**)&p);} + ~CComPtr() { + Release();} +}; + +template + class CComQIPtr : public CComPtr +{ +public: + CComQIPtr(IUnknown* q) { + if (q != NULL) q->QueryInterface(g, (void **)&p);} +}; + +class CComVariant : public VARIANT +{ +public: + CComVariant() + {VariantInit(this);} + ~CComVariant() + {VariantClear(this);} +}; Modifié: trunk/base.cpp =================================================================== --- trunk/base.cpp 2008-11-11 00:27:20 UTC (rev 139) +++ trunk/base.cpp 2008-11-16 14:59:52 UTC (rev 140) @@ -81,5 +81,6 @@ MessageBox(hMainWnd, pszErrBuf, NULL, MB_ICONERROR); delete pszErrBuf; pszErrBuf = NULL; + lastRes = S_OK; } } Modifié: trunk/base.h =================================================================== --- trunk/base.h 2008-11-11 00:27:20 UTC (rev 139) +++ trunk/base.h 2008-11-16 14:59:52 UTC (rev 140) @@ -65,7 +65,20 @@ #pragma warning(disable:4995) #include +// Activer la définition suivante si les modèles de classes ATL ne sont +// pas disponibles sur votre ordinateur (ce qui est normalement le cas +// des utilisateurs de Visual C++ 2005 Express, sauf s'ils se sont procurés +// ces classes depuis une autre source ; ils auront dans ce cas l'erreur suivante : +// "fatal error C1083: Impossible d'ouvrir le fichier include : 'atlbase.h'" ; +// voir commentaires dans le fichier atlbase_ptvm.h) : + +// #define DONT_HAVE_ATL_TEMPLATES + +#ifdef DONT_HAVE_ATL_TEMPLATES + #include "atlbase_ptvm.h" +#else #include +#endif #include "resource.h" From pouchintv-dev at baysse.fr Thu Nov 20 13:15:06 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Thu, 20 Nov 2008 13:15:06 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r141 - trunk Message-ID: <20081120121506.70A615F3A9@mail.baysse.fr> Author: gingko Date: 2008-11-20 13:15:06 +0100 (jeu, 20 nov 2008) New Revision: 141 Modified: trunk/Pouchin TV.vcproj trunk/base.cpp trunk/base.h trunk/capture.cpp trunk/capture.h trunk/channels.cpp trunk/channels.h trunk/chanutils.cpp trunk/chanutils.h trunk/epg.cpp trunk/graph.cpp trunk/graph.h trunk/ini.cpp trunk/main.cpp trunk/main.h trunk/mpeg2defs.h trunk/parse.cpp trunk/record.cpp trunk/recprog.cpp trunk/sbuffer.cpp trunk/sbuffer.h trunk/search.cpp trunk/settings.cpp trunk/xml.cpp Log: Utilisation de types énumérés locaux pour désigner les types de flux audio et vidéo pris en charge par PouchinTV Mod. Suppression du descripteur "mpeg4_pid" dans les descripteurs de chaînes : considérant qu'une chaîne n'a en principe qu'un seul flux vidéo principal, il m'a semblé préférable d'utiliser le descripteur "video_pid" déjà existant et d'indiquer le type de celui-ci à l'aide d'une variable spécifique. Reconnaissance de la présence des flux audio "Extended AC3" (en attendant de pouvoir les décoder). Factorisations dans graph.cpp, notamment par l'ajout des fonctions "connect_pin_to_filter" et "get_and_add_codec". Utilisations de fonctions distinctes pour lancer et stopper le graphe (dans l'idée plus ou moins expérimentale de limiter les ressources - ici 'pControl' (IMediaControl) devenant locale et d'usage éphémère - réservées en permanence). Ajout d'un certain nombre de tests d'erreur en mode debugging. Mémorisation de l'état "suspendu" de l'audio et de la vidéo afin qu'un changement de chaîne en mode suspendu n'ait pas pour effet de "désuspendre" les sorties de ces modes. Ajout d'un paramètre à la fonction "rebranche" indiquant si le rebranchement doit être associé ou non à une réinitialisation du choix de la piste son selon la préférence de configuration AC3. Une partie du contenu de cette fonction est par ailleurs déplacée en tant que fonction membre de la classe "Chaine". Des fonctions "branche_son" et "debranche_son" sont également créées pour mieux en gérer cet aspect. La fonction "debranche_tout" est renommée "debranche_tous_pids" ce qui correspond mieux à son rôle réel. Le branchement initial des flux au lancement est réorganisé de façon à ce qu'un lancement en mode minimisé ne produise pas un branchement suivi d'un débranchement immédiat (on se contente de ne rien brancher du tout ...). La fonction "InitDshow" est supprimée (son contenu est déplacé directement à son ancien point d'appel) : les deux actions majeures qu'elle effectuait n'avaient pas de raison majeure d'être liés ensemble, et il est plus aisé ainsi d'envisager de les dissocier. Correction d'un bug dans l'EPG qui faisait que la demande d'enregistrement d'une chaîne ne fonctionnait pas si le bouton "Enregistré" était pressé sans que la sélection initiale ait été modifiée. Quelques ajustements de types de variables (essentiellement pour éviter des avertissements en mode 64 bits). Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/Pouchin TV.vcproj 2008-11-20 12:15:06 UTC (rev 141) @@ -137,6 +137,7 @@ UsePrecompiledHeader="0" WarningLevel="4" DebugInformationFormat="3" + DisableSpecificWarnings="4480" /> + #include #endif #include "resource.h" Modifié: trunk/capture.cpp =================================================================== --- trunk/capture.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/capture.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -68,7 +68,7 @@ } CCapture_TS::CCapture_TS( - HANDLE hFil, int pmt, int video, + HANDLE hFil, UINT16 pmt, UINT16 video, const liste_pistes & lst_sons, const liste_pistes & lst_autr) : CCapture(hFil), @@ -115,34 +115,34 @@ // Ajout d'un bloc "Pack Header" : // (retourne la taille du bloc ajouté, ou bien 0 si échec) - size_t addPackHeader(); + UINT32 addPackHeader(); // Ajout d'un bloc "System Header" : // (retourne la taille du bloc ajouté, ou bien 0 si échec) - size_t addSystemHeader(); + UINT32 addSystemHeader(); // Ajout d'un bloc PES de base, dérivé du bloc source 'p_src_hdr' : // (retourne la taille du bloc ajouté, ou bien 0 si échec) - size_t addPES_Header(IF_DEBUG(LPCSTR nom_debug)); + UINT32 addPES_Header(IF_DEBUG(LPCSTR nom_debug)); // Ajout d'un bloc PES d'extension, dérivé du bloc source 'p_src_hdr' : // (retourne la taille du bloc ajouté, ou bien 0 si échec) - size_t addPES_extHeader(); + UINT32 addPES_extHeader(); // Compléter le bloc avec un PES de padding, en laissant néanmoins // éventuellement un espace de taille égale = 'guard' à la fin. // Si l'ajustement requis est très faible, alors l'ajustement se fera, à la place, // en ajoutant des octets de "stuffing" dans l'en-tête. // Retourne la quantité de données *ajoutées* au buffer : - size_t add_Padding(size_t guard=0); + UINT32 add_Padding(size_t guard=0); // Ajout de données dans le bloc. Retourne 'true' si la totalité des données ont pu être ajoutées, // 'false' sinon ; dans ce dernier cas, rien n'est modifié. - bool addData(const UINT8 * ptr, size_t size); + bool addData(const UINT8 * ptr, UINT32 size); // Ajout de données dans le bloc. Retourne 'true' si la totalité des données ont pu être ajoutées, // 'false' sinon ; dans ce dernier cas, 'ptr' et 'size' sont ajustés sur les données restantes. - bool addPES_data(const UINT8 * & ptr, size_t & size); + bool addPES_data(const UINT8 * & ptr, UINT32 & size); // Ajustement de l'index du buffer pour que les données subséquentes s'inscrivent // à partir de l'adresse 'ptr' : @@ -154,7 +154,7 @@ // sont ajoutées. // La fonction retourne le nombre d'octets *ajoutés* (en-têtes, remplissage, etc) par rapport au flot // d'origine. - size_t build(bool start, const UINT8 * & ptr, size_t & size IF_DEBUG_CB(LPCSTR nom_debug)); + UINT32 build(bool start, const UINT8 * & ptr, UINT32 & size IF_DEBUG_CB(LPCSTR nom_debug)); // Vidange du tampon dans le fichier : void write_to_file(); @@ -172,9 +172,9 @@ // sont ajoutées. // La fonction retourne le nombre d'octets *ajoutés* (en-têtes, remplissage, etc) par rapport au flot // d'origine. -size_t PS_chunk::build(bool start, const UINT8 * & ptr, size_t & size IF_DEBUG_CB(LPCSTR nom_debug)) +UINT32 PS_chunk::build(bool start, const UINT8 * & ptr, UINT32 & size IF_DEBUG_CB(LPCSTR nom_debug)) { - size_t added_bytes = 0; + UINT32 added_bytes = 0; if (start) { added_bytes += addPackHeader(); @@ -183,7 +183,7 @@ cGrabber.sys_header_set = true; } // - size_t hdsize = addPES_Header(IF_DEBUG(nom_debug)); + UINT32 hdsize = addPES_Header(IF_DEBUG(nom_debug)); // Le premier en-tête existait dans le tampon source, on le saute donc en lecture ptr += hdsize; size -= hdsize; @@ -204,7 +204,7 @@ // Ajout de données dans le bloc. Retourne 'true' si la totalité des données ont pu être ajoutées, // 'false' sinon ; dans ce dernier cas, rien n'est modifié. -bool PS_chunk::addData(const UINT8 * ptr, size_t size) +bool PS_chunk::addData(const UINT8 * ptr, UINT32 size) { if (ixBuf+size <= _countof(buffer)) { memcpy(&buffer[ixBuf], ptr, size); @@ -216,7 +216,7 @@ // Ajout de données dans le bloc. Retourne 'true' si la totalité des données ont pu être ajoutées, // 'false' sinon ; dans ce dernier cas, 'ptr' et 'size' sont ajustés sur les données restantes. -bool PS_chunk::addPES_data(const UINT8 * & ptr, size_t & size) +bool PS_chunk::addPES_data(const UINT8 * & ptr, UINT32 & size) { UINT32 adjustedSize = UINT32(size); bool fit = ixBuf+size <= _countof(buffer); @@ -234,7 +234,7 @@ } // Ajout d'un bloc "Pack header" : -size_t PS_chunk::addPackHeader() +UINT32 PS_chunk::addPackHeader() { if (sizeof(PS_chunk)-ixBuf >= sizeof(PS_PackHeader)) { PS_PackHeader & phdr = *new(&buffer[ixBuf])PS_PackHeader(); // "Placement" new @@ -250,7 +250,7 @@ } // Ajout d'un bloc "System Header" : -size_t PS_chunk::addSystemHeader() +UINT32 PS_chunk::addSystemHeader() { if (sizeof(PS_chunk)-ixBuf >= sizeof(PS_SystemHeader)+2*sizeof(PS_SH_entry)) { PS_SystemHeader & shd = *new (&buffer[ixBuf])PS_SystemHeader(); // "Placement" new @@ -273,7 +273,7 @@ // Ajout d'un bloc PES de base, dérivé du bloc source 'p_src_hdr' : // (retourne la taille du bloc ajouté, ou bien 0 si échec) -size_t PS_chunk::addPES_Header(IF_DEBUG(LPCSTR nom_debug)) +UINT32 PS_chunk::addPES_Header(IF_DEBUG(LPCSTR nom_debug)) { if (sizeof(PS_chunk)-ixBuf >= sizeof(PS_hdr_wd)) { PS_hdr_wd & dst_hdr = *new (&buffer[ixBuf]) PS_hdr_wd(src_hdr); // "Placement" new @@ -309,7 +309,7 @@ } // Ajout d'un bloc PES d'extension, dérivé du bloc source 'p_src_hdr' : -size_t PS_chunk::addPES_extHeader() +UINT32 PS_chunk::addPES_extHeader() { if (sizeof(PS_chunk)-ixBuf >= sizeof(PS_hdr_wd)) { PS_hdr_wd & dst_hdr = *new (&buffer[ixBuf])PS_hdr_wd(src_hdr); // "Placement" new @@ -328,7 +328,7 @@ // Compléter le bloc avec un PES de padding, en laissant néanmoins // éventuellement un espace de taille égale = 'guard' à la fin. // Retourne la quantité de données *ajoutées* au buffer. -size_t PS_chunk::add_Padding(size_t guard) +UINT32 PS_chunk::add_Padding(size_t guard) { UINT16 remain = UINT16(sizeof(buffer)-guard-ixBuf); @@ -361,7 +361,7 @@ // ************************************************************ -PS_buffer::PS_buffer(int used_pid, UINT8 maxChnk IF_DEBUG_CB(LPCSTR nom_dbg)) : +PS_buffer::PS_buffer(UINT16 used_pid, UINT8 maxChnk IF_DEBUG_CB(LPCSTR nom_dbg)) : pcGrab(NULL), IF_DEBUG_CA(nom_debug(nom_dbg)) pid(used_pid), @@ -406,7 +406,7 @@ if (valid && uw_th.p_payload) { // Paquet valide et "Payload" présent - size_t ptr_size = &p.bytes[TS_SIZE]-uw_th.p_payload; + 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); @@ -416,10 +416,10 @@ void PS_buffer::send() { const UINT8 * ptr = data_ptr(); - size_t size = data_size; + UINT32 size = data_size; const PS_hdr_wd & hdr = *reinterpret_cast(ptr); bool start = true; - size_t added_bytes = 0; + UINT32 added_bytes = 0; while (size>0) { PS_chunk chunk(hdr, *this); @@ -432,7 +432,7 @@ pcGrab->byte_count += added_bytes; } -CCapture_PS::CCapture_PS(HANDLE hFil, int video, int audio) : +CCapture_PS::CCapture_PS(HANDLE hFil, UINT16 video, UINT16 audio) : CCapture(hFil), first_pcr(0), curr_pcr(0), Modifié: trunk/capture.h =================================================================== --- trunk/capture.h 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/capture.h 2008-11-20 12:15:06 UTC (rev 141) @@ -56,14 +56,14 @@ class CCapture_TS : public CCapture { - int video_pid; - int pmt_pid; + UINT16 video_pid; + UINT16 pmt_pid; liste_pistes sons; liste_pistes autr; public: - CCapture_TS(HANDLE hFil, int pmt, int video, + CCapture_TS(HANDLE hFil, UINT16 pmt, UINT16 video, const liste_pistes & lst_sons, const liste_pistes & lst_autr); @@ -77,12 +77,12 @@ CCapture_PS * pcGrab; IF_DEBUG(LPCSTR nom_debug;) - int pid; + UINT16 pid; bool valid; UINT8 continuity_counter; public: - PS_buffer(int used_pid, UINT8 maxChnk IF_DEBUG_CB(LPCSTR nom_dbg)); + PS_buffer(UINT16 used_pid, UINT8 maxChnk IF_DEBUG_CB(LPCSTR nom_dbg)); void traite_paquet(const TS_packet & p); @@ -116,7 +116,7 @@ UINT32 curr_pcr_second; // Seconde entière du PCR courant (pour tests statistiques) UINT32 pck_pcr_count; // Comptage des paquets "TS" depuis le dernier PCR reçu UINT32 pcr_rate; // Taux d'incrémentation du PCR par paquet - size_t byte_count; // Comptage des octets émis en mode PS pour calcul "multiplex rate" + UINT32 byte_count; // Comptage des octets émis en mode PS pour calcul "multiplex rate" UINT32 byte_mux_rate; // "multiplex rate" courant, calculé en octets par seconde RateHelper pcr_rate_helper; // assistance au calcul de l'intervalle de temps moyen entre paquets TS RateHelper mux_rate_helper; // assistance au calcul du "multiplex rate" @@ -126,7 +126,7 @@ PS_buffer audio_build; public: - CCapture_PS(HANDLE hFil, int video, int audio); + CCapture_PS(HANDLE hFil, UINT16 video, UINT16 audio); virtual void traite_paquet(const TS_packet & p); Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/channels.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -36,6 +36,7 @@ int ixChaineCourante = -1; int ixSonCourant = 0; long volumeCourant = 0; +bool suspendu = true; // 'true' si vidéo et audio suspendus (à l'initialisation, ou si minimisé + 'suspend_minimized') // Taille des images des chaines (largeur et longueur) #define TAILLE_IMAGE_CHAINE 16 @@ -63,32 +64,88 @@ ChainePMT::ChainePMT() : video_pid(0), - mpeg4_pid(0), + video_type(vst_Unknown), pcr_pid(0) { } bool ChainePMT::operator == (const ChainePMT & cpmt) const { - if (video_pid!=cpmt.video_pid || mpeg4_pid!=cpmt.mpeg4_pid || pcr_pid!=cpmt.pcr_pid) + if (video_pid!=cpmt.video_pid || video_type!=cpmt.video_type || pcr_pid!=cpmt.pcr_pid) return false; return sons==cpmt.sons && autr==cpmt.autr; } char ChainePMT::norme(void) const { - return video_pid!=0 ? - (mpeg4_pid!=0 ? 'X': '2') : - (mpeg4_pid!=0 ? '4': '?'); + switch (video_type) { + case vst_MPEG2: + return '2'; + case vst_H264: + case vst_H264_encrypted: + return '4'; + } + return '?'; } // Constructeur : -Chaine::Chaine() +Chaine::Chaine() : + canal_no(0), + pmt_pid(0), + frequence(0), + etat(ec_preferee), + numeroChaine(0), + emi_count(0), + hImage(NULL) { - memset(this, 0, sizeof(*this)); - etat=ec_preferee; + nom[0] = 0; + groupe[0] = 0; } +static void branche_son(une_piste son) +{ + ULONG pid = son.pid; + HRESULT hr; + + if (pid!=0) { + switch (son.type) { + + case ast_MPEG2: + hr = pMapSound->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); + myprintf(L"%?erreur pid son, hr=0x%08x\n", FAILED(hr), hr); + break; + + case ast_AC3: + hr = pMapAc3->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); + myprintf(L"%?erreur pid ac3, hr=0x%08x\n", FAILED(hr), hr); + break; + + default: + myprintf(L"Type de piste audio non identifié\n"); + } + } +} + +static void debranche_son(une_piste son) +{ + ULONG pid = son.pid; + + if (pid!=0) + switch (son.type) { + + case ast_MPEG2: + pMapSound->UnmapPID(1, &pid); + break; + + case ast_AC3: + pMapAc3->UnmapPID(1, &pid); + break; + + default: + myprintf(L"Type de piste audio non identifié\n"); + } +} + HBITMAP Chaine::ChargeIcone() { if (hImage==INVALID_HANDLE_VALUE) @@ -125,6 +182,50 @@ return swprintf_s(pstr, bufSize, L"%4i : %S", numeroChaine, nom); } +// Mappage de tous les PIDs de la chaîne (la fréquence est présumée déjà syntonisée) ; +// Si 'reset_son' est 'true', alors le canal son est, en même temps, remis à sa +// valeur par défaut, selon préférences globales de l'utilisateur : +HRESULT Chaine::branche(bool reset_son) const +{ + myprintf(L"SID %i, TSID %i, ONID %i, freq : %i\n", SID, TSID, ONID, frequence); + + ULONG pid = video_pid; + HRESULT hr = E_FAIL; // valeur par défaut + + if (pid) { + switch (video_type) { + case vst_MPEG2: + if (pMapMPEG2) + hr = pMapMPEG2->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); + break; + default: + hr=E_FAIL; + } + myprintf(L"%?erreur pid video, hr=0x%08x\n", FAILED(hr), hr); + } + + if (reset_son) { + ixSonCourant = 0; // par défaut + + if (use_ac3) { // AC3 par défaut : chercher s'il y a une piste AC3 + for (int i=0; iMapPID(1, &pid, MEDIA_MPEG2_PSI); + myprintf(L"%?erreur pid pmt, hr=0x%08x\n", FAILED(hr), hr); + return hr; +} + /** * Recherche de l'index correspondant à un numéro de chaîne 'numChaine'. * Retourne -1 si pas trouvé. @@ -265,7 +366,9 @@ return true; } -static void debranche_tout(CComPtr & pMap) +// Débranchement de tous les flux élémentaires (identifiés par PID) qui sont couramment +// présentés sur la connexion pMap. +static void debranche_tous_pids(CComPtr & pMap IF_DEBUG_CB(LPCSTR nom_itf)) { PID_MAP maps[8]; ULONG nbPids; @@ -277,135 +380,107 @@ pEnumMap->Next(_countof(maps), maps, &nbPids); } + myprintf(L"debranche %u pid(s) sur pMap=%S\n", nbPids, nom_itf); for (ULONG i=0; iUnmapPID(1, &maps[i].ulPID); myprintf(L"%?unmap foiré, hr=0x%08x\n", FAILED(hr), hr); } } +// Déconnexion globale des sorties vidéo et audio : void debranche() -{ // (noms de fonctions à revoir ??) - debranche_tout(pMapMPEG2); - debranche_tout(pMapSound); - debranche_tout(pMapAc3); - debranche_tout(pMapPmt); +{ + if (!suspendu) { + debranche_tous_pids(pMapMPEG2 IF_DEBUG_CB("pMapMPEG2")); + debranche_tous_pids(pMapSound IF_DEBUG_CB("pMapSound")); + debranche_tous_pids(pMapAc3 IF_DEBUG_CB("pMapAc3")); + debranche_tous_pids(pMapPmt IF_DEBUG_CB("pMapPmt")); + + suspendu = true; + } } -void switch_audio(int old_son, int new_son) +// Reconnexion globale des sorties vidéo et audio ; +// si 'reset_son' est 'true', alors le canal son est, en même temps, remis à sa +// valeur par défaut, selon les préférences globales de l'utilisateur : +bool rebranche(bool reset_son) { - const une_piste * son_courant = Canaux[ixChaineCourante].sons.tbl; - ULONG old_pid = son_courant[old_son].pid; - ULONG new_pid = son_courant[new_son].pid; + // 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()) { - int old_type = son_courant[old_son].type; - int new_type = son_courant[new_son].type; - - if (old_type==1) { - pMapAc3->UnmapPID(1, &old_pid); - } else { - pMapSound->UnmapPID(1, &old_pid); + if (suspendu) { + suspendu = false; + Canaux[ixChaineCourante].branche(reset_son); + } + return true; } + return false; +} - if (new_type==1) { - pMapAc3->MapPID(1, &new_pid, MEDIA_ELEMENTARY_STREAM); - } else { - pMapSound->MapPID(1, &new_pid, MEDIA_ELEMENTARY_STREAM); +void switch_audio(int new_son) +{ + if (new_son != ixSonCourant) { + const une_piste * son_courant = Canaux[ixChaineCourante].sons.tbl; + + debranche_son(son_courant[ixSonCourant]); + branche_son(son_courant[new_son]); + + ixSonCourant=new_son; } - - ixSonCourant=new_son; } // Changement de chaîne pour la chaîne dont l'index est donné en paramètre. // Retourne 0 si pas d'erreur, 1 si le changement n'a pas pu avoir lieu -int change_chaine(int ixChaine) +// (mettre -1 pour désactiver la sélection de chaîne) +HRESULT change_chaine(int ixChaine) { - bool freq_differente = true; + bool freq_differente = true; + bool sauve_suspend = suspendu; + bool reset_son = ixChaine!=ixChaineCourante; + if (ixChaine_ok(ixChaineCourante) && ixChaine_ok(ixChaine) && - Canaux[ixChaineCourante].frequence == Canaux[ixChaine].frequence) + Canaux[ixChaineCourante].frequence == Canaux[ixChaine].frequence && + Canaux[ixChaineCourante].video_type == Canaux[ixChaine].video_type) { freq_differente = false; } if (freq_differente && recording()) - return 1; // On ne change pas de fréquence si enregistrement en cours + return S_FALSE; // On ne change pas de fréquence si enregistrement en cours ixChaineCourante = -1; // doit être égal à -1 pendant les transitions (à cause du filtre PMT) - debranche(); + if (!suspendu) { + debranche(); + } if (ixChaine >= 0) { + myprintf(L"zappe %i\n", ixChaine+1); + const Chaine & nouveau_canal = Canaux[ixChaine]; - myprintf(L"zappe %i\n", ixChaine+1); - myprintf(L"SID %i, TSID %i, ONID %i, freq : %i\n", nouveau_canal.SID, nouveau_canal.TSID, nouveau_canal.ONID, nouveau_canal.frequence); - if (freq_differente) change_frequence(nouveau_canal.frequence); - ULONG pid = nouveau_canal.video_pid; - HRESULT hr; + ixChaineCourante = ixChaine_ok(ixChaine) ? ixChaine : -1; - if (pid) { - hr = pMapMPEG2->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); - myprintf(L"%?erreur pid video, hr=0x%08x\n", FAILED(hr), hr); - } + // Ne reconnecter l'interface que si elle l'était avant : + if (!sauve_suspend) + rebranche(reset_son); + } else { + // ixChaine < 0 pour désélection de chaîne - int piste_ac3=-1; - - for (int i=0; iMapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); - myprintf(L"%?erreur pid ac3, hr=0x%08x\n", FAILED(hr), hr); - } - } else { // passe en MPEG audio - pid = nouveau_canal.sons.tbl[0].pid; - if (pid) { - hr = pMapSound->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); - ixSonCourant=0; - myprintf(L"%?erreur pid son, hr=0x%08x\n", FAILED(hr), hr); - } - } - - // pmt - - pid = nouveau_canal.pmt_pid; - hr = pMapPmt->MapPID(1, &pid, MEDIA_MPEG2_PSI); - myprintf(L"%?erreur pid pmt, hr=0x%08x\n", FAILED(hr), hr); - + // Restaurer 'suspendu' après désélection de chaîne sinon l'affichage + // ne redémarre pas à l'issue d'une recherche de chaînes : + suspendu = sauve_suspend; } - ixChaineCourante = ixChaine_ok(ixChaine) ? ixChaine : -1; - - return 0; + return S_OK; } -void rebranche() -{ - const Chaine & canal_courant = Canaux[ixChaineCourante]; - HRESULT hr; - - ULONG pid = canal_courant.video_pid; - hr = pMapMPEG2->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); - myprintf(L"%?erreur pid video, hr=0x%08x\n", FAILED(hr), hr); - - pid = canal_courant.sons.tbl[ixSonCourant].pid; - if (canal_courant.sons.tbl[ixSonCourant].type == 1) { - hr = pMapAc3->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); - myprintf(L"%?erreur pid ac3, hr=0x%08x\n", FAILED(hr), hr); - } else { - hr = pMapSound->MapPID(1, &pid, MEDIA_ELEMENTARY_STREAM); - myprintf(L"%?erreur pid son, hr=0x%08x\n", FAILED(hr), hr); - } -} - void set_volume(long volume) { CComQIPtr pBas(pGraph); Modifié: trunk/channels.h =================================================================== --- trunk/channels.h 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/channels.h 2008-11-20 12:15:06 UTC (rev 141) @@ -36,11 +36,14 @@ SYSTEMTIME fin; char nom[86]; char desc[256]; + + Emission() { + ZeroMemory(this, sizeof(*this));} }; struct ChainePMT { UINT16 video_pid; - UINT16 mpeg4_pid; + VideoStreamType video_type; UINT16 pcr_pid; liste_pistes sons; liste_pistes autr; @@ -57,6 +60,13 @@ UINT16 TSID; UINT16 SID; UINT16 numero_nit;// Numéro de chaîne original + + ChaineIDs() : + ONID(0), + TSID(0), + SID(0), + numero_nit(0) + {} }; enum EtatChaine { @@ -92,14 +102,20 @@ (numeroChaine == canal2.numeroChaine && _stricmp(nom, canal2.nom) > 0); } // Génération du nom affichable pour le menu int toMenuString(LPWSTR pstr, size_t bufSize) const; + + // Mappage de tous les PIDs de la chaîne (la fréquence est présumée déjà syntonisée) ; + // Si 'reset_son' est 'true', alors le canal son est, en même temps, remis à sa + // valeur par défaut, selon préférences globales de l'utilisateur : + HRESULT branche(bool reset_son) const; }; // Tableau des chaînes extern std::vector Canaux; -extern int ixChaineCourante; // Index de la chaîne couramment utilisée -extern int ixSonCourant; // Index de la piste sonore couramment utilisée +extern int ixChaineCourante; // Index de la chaîne couramment utilisée +extern int ixSonCourant; // Index de la piste sonore couramment utilisée extern long volumeCourant; // Niveau de volume sonore courant +extern bool suspendu; // 'true' si vidéo et audio suspendus (à l'initialisation, ou si minimisé + 'suspend_minimized') void change_frequence(ULONG freq); @@ -107,17 +123,23 @@ // Changement de chaîne pour la chaîne dont l'index est donné en paramètre. // Retourne 0 si pas d'erreur, 1 si le changement n'a pas pu avoir lieu -int change_chaine(int ixChaine); +// (mettre -1 pour désactiver la sélection de chaîne) +HRESULT change_chaine(int ixChaine); // Changement de piste son : -void switch_audio(int old_son, int new_son); +void switch_audio(int new_son); // Changement de volume sonore : void set_volume(long volume); +// Déconnexion globale des sorties vidéo et audio : void debranche(); -void rebranche(); +// Reconnexion globale des sorties vidéo et audio ; +// si 'reset_son' est 'true', alors le canal son est, en même temps, remis à sa +// valeur par défaut, selon les préférences globales de l'utilisateur : +bool rebranche(bool reset_son); + /** * Recherche de l'index correspondant à un numéro de chaîne 'numChaine'. * Retourne -1 si pas trouvé. Modifié: trunk/chanutils.cpp =================================================================== --- trunk/chanutils.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/chanutils.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -61,7 +61,7 @@ return false; } -int liste_pistes::ajoute(UINT16 newpid, UINT8 newtype, LPCSTR newlang) +int liste_pistes::ajoute(UINT16 newpid, AudioStreamType newtype, LPCSTR newlang) { if (nbr<_countof(tbl)) { une_piste & piste = tbl[nbr]; Modifié: trunk/chanutils.h =================================================================== --- trunk/chanutils.h 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/chanutils.h 2008-11-20 12:15:06 UTC (rev 141) @@ -39,16 +39,32 @@ #include +enum VideoStreamType : UINT8 +{ + vst_Unknown = 0xff, + vst_MPEG2 = 0, + vst_H264, + vst_H264_encrypted // -> va sans doute être utilisé prochainement +}; + +enum AudioStreamType : UINT8 +{ + ast_Unknown = 0xff, + ast_MPEG2 = 0, // 0 = MPEG2 Audio Layer II + ast_AC3, // 1 = AC3 + ast_EAC3 // 2 = Extended AC3 +}; + // Nombre max de pistes son par chaîne #define NB_MAX_PISTES 32 struct une_piste { - UINT16 pid; - UINT8 type; // si son : 0 = normal, 1 = AC3; réservé si autres - char lang[8]; + UINT16 pid; + AudioStreamType type; // si son : voir AudioStreamType; ast_Unknown (réservé) si autres + char lang[8]; // Efface le tableau de caractère, car pose des problèmes des fois si pas effacé - une_piste() : pid(0), type(0) {ZeroMemory(lang, sizeof(lang)); }; + une_piste() : pid(0), type(ast_Unknown) {ZeroMemory(lang, sizeof(lang)); }; une_piste(const une_piste &piste); bool operator == (const une_piste & up) const @@ -59,13 +75,13 @@ }; struct liste_pistes { - UINT16 nbr; - une_piste tbl[NB_MAX_PISTES]; + UINT16 nbr; + une_piste tbl[NB_MAX_PISTES]; liste_pistes() : nbr(0) {}; bool cherche_pid(UINT16 pid) const; - int ajoute(UINT16 newpid, UINT8 newtype=0, LPCSTR newlang=NULL); + int ajoute(UINT16 newpid, AudioStreamType newtype, LPCSTR newlang=NULL); bool operator == (const liste_pistes & lp) const; bool operator != (const liste_pistes & lp) const {return ! operator == (lp);}; }; Modifié: trunk/epg.cpp =================================================================== --- trunk/epg.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/epg.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -98,6 +98,7 @@ if (visible_index >= 0) { ListView_SetItemState(hListItem, visible_index, LVIS_SELECTED, LVIS_SELECTED); + ListView_SetSelectionMark(hListItem, visible_index); ListView_EnsureVisible(hListItem, visible_index, FALSE); } } @@ -177,18 +178,20 @@ // le reste à zéro (implicite) }; - ListView_GetItem(hListItem, &item); + if (ListView_GetItem(hListItem, &item)) { + int ixChaine = trouve_chaine_par_sid(LOWORD(item.lParam)); + Programme prog; - int ixChaine = trouve_chaine_par_sid(LOWORD(item.lParam)); - Programme prog; + if (!chaineToProg(ixChaine, LOBYTE(HIWORD(item.lParam)), prog) || !prog.verifie(false)) + return FALSE; + prog.methode = (MethodeEnregistrement)SendDlgItemMessage(hDlg, IDC_METHOD_EPG, CB_GETCURSEL, 0, 0); + prog.audio = (AudioMode)SendDlgItemMessage(hDlg, IDC_AUDIO_EPG, CB_GETCURSEL, 0, 0); - if (!chaineToProg(ixChaine, LOBYTE(HIWORD(item.lParam)), prog) || !prog.verifie(false)) - return FALSE; - prog.methode = (MethodeEnregistrement)SendDlgItemMessage(hDlg, IDC_METHOD_EPG, CB_GETCURSEL, 0, 0); - prog.audio = (AudioMode)SendDlgItemMessage(hDlg, IDC_AUDIO_EPG, CB_GETCURSEL, 0, 0); + Programmes.push_back(prog); + finalize_prog_change(); + } else + affiche_erreurs(L"Item non sélectionné"); - Programmes.push_back(prog); - finalize_prog_change(); return TRUE; } } return FALSE; Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/graph.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -38,7 +38,6 @@ #include CComPtr pGraph; -CComPtr pControl; CComPtr pVMRControl; @@ -82,7 +81,7 @@ if (FAILED(GetRunningObjectTable(0, &pROT))) return E_FAIL; - StringCchPrintfW(wsz, _countof(wsz), L"FilterGraph %08x pid %08x", (DWORD_PTR)&pGraph.p, GetCurrentProcessId()); + swprintf_s(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)&pGraph.p, GetCurrentProcessId()); HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker); @@ -113,11 +112,8 @@ myprintf(L"callback ok\n"); - if (pControl) { - pControl->Stop(); - } + graph_Stop(); - myprintf(L"stop ok\n"); #if LOG_DSHOW @@ -162,9 +158,10 @@ for (int i=0; i & pFilter) { @@ -181,21 +178,44 @@ return hr; } -static HRESULT connect_filters(CComPtr & source, CComPtr & dest) +// Création et ajout d'un filtre de type codec défini par son nom, et devant +// de plus correspondre au type 'type' et au sous-type 'subtype' définis. +static HRESULT get_and_add_codec(LPCWSTR nom, GUID type, GUID subtype, + LPCWSTR infotype, CComPtr & pFilter) { - CComPtr pPin1; - CComPtr pPin2; - HRESULT hr = cherche_pin(source, PINDIR_OUTPUT, pPin1); + HRESULT hr = get_filter(type, subtype, nom, pFilter); if (SUCCEEDED(hr)) { - hr = cherche_pin(dest, PINDIR_INPUT, pPin2); - if (SUCCEEDED(hr)) - hr = pGraph->ConnectDirect(pPin1, pPin2, NULL); + myprintf(L"Ajout codec %s\n", infotype); + + hr = pGraph->AddFilter(pFilter, nom); + if (FAILED(hr)) + return erreur(L"Le codec %s \"%s\" n'a pas pu être inséré dans le graphe", + hr, infotype, nom); } + return hr; +} +static HRESULT connect_pin_to_filter(CComPtr & pOutPin, CComPtr & pFilter) +{ + CComPtr pInPin; + HRESULT hr = cherche_pin(pFilter, PINDIR_INPUT, pInPin); + + if (SUCCEEDED(hr)) + hr = pGraph->ConnectDirect(pOutPin, pInPin, NULL); return hr; } +static HRESULT connect_filters(CComPtr & source, CComPtr & dest) +{ + CComPtr pOutPin; + HRESULT hr = cherche_pin(source, PINDIR_OUTPUT, pOutPin); + + if (SUCCEEDED(hr)) + hr = connect_pin_to_filter(pOutPin, dest); + return hr; +} + static HRESULT getFrequencyFilter(CComPtr & pNetworkTuner) { HRESULT hr = pNetworkTuner.QueryInterface(&pBDAControl); @@ -302,8 +322,6 @@ return S_OK; } - CComPtr pVideoPin; - AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_Video; am.subtype = MEDIASUBTYPE_MPEG2_VIDEO; @@ -335,26 +353,19 @@ mvi.hdr.bmiHeader.biWidth = 720; mvi.hdr.bmiHeader.biHeight = 576; + CComPtr pVideoPin; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"video", &pVideoPin); + if (FAILED(hr)) return erreur(L"La broche vidéo MPEG2 n'a pas pu être créée", hr); // le décodeur vidéo - hr = get_filter(MEDIATYPE_Video, MEDIASUBTYPE_MPEG2_VIDEO, filtreMPEG2, pVideoCodec); - if (SUCCEEDED(hr)) { - myprintf(L"Ajout video MPEG2\n"); + hr = get_and_add_codec(filtreMPEG2, MEDIATYPE_Video, MEDIASUBTYPE_MPEG2_VIDEO, + L"vidéo MPEG2", pVideoCodec); - hr = pGraph->AddFilter(pVideoCodec, filtreMPEG2); + if (SUCCEEDED(hr)) { + hr = connect_pin_to_filter(pVideoPin, pVideoCodec); if (FAILED(hr)) - return erreur(L"Le codec vidéo MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreMPEG2); - - CComPtr pPinEntree; - - hr = cherche_pin(pVideoCodec, PINDIR_INPUT, pPinEntree); - if (SUCCEEDED(hr)) - hr = pGraph->ConnectDirect(pVideoPin, pPinEntree, NULL); - - if (FAILED(hr)) return erreur(L"Impossible de connecter le démultiplexeur au codec vidéo MPEG2 \"%s\"", hr, filtreMPEG2); } else { hr = pGraph->RenderEx(pVideoPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); @@ -362,18 +373,16 @@ return erreur(L"Pas de rendu possible depuis la broche vidéo MPEG2", hr); } - pVideoPin.QueryInterface(&pMapMPEG2); + hr = pVideoPin.QueryInterface(&pMapMPEG2); + myprintf(L"%?erreur pMapMPEG2, hr=0x%08x\n", FAILED(hr), hr); return hr; } HRESULT init_vmr() { + HRESULT hr = graph_Stop(); - pControl->Stop(); - - HRESULT hr; - // crée le VMR hr = create_and_add_filter(MyV(CLSID_VideoMixingRenderer), L"Video Mixing Renderer", pVMR); @@ -429,8 +438,10 @@ return erreur(L"Échec de SetRenderingPrefs", hr); } - pNotify->AdviseSurfaceAllocator(0x118218, pSurfAlloc); - pSurfAlloc->AdviseNotify(pNotify); + hr = pNotify->AdviseSurfaceAllocator(0x118218, pSurfAlloc); + myprintf(L"%?erreur AdviseSurfaceAllocator, hr=0x%08x\n", FAILED(hr), hr); + hr = pSurfAlloc->AdviseNotify(pNotify); + myprintf(L"%?erreur AdviseNotify, hr=0x%08x\n", FAILED(hr), hr); } if (use_vmr_deinterlace) { @@ -498,10 +509,12 @@ return hr; } - pVMRControl->SetVideoClippingWindow(hMainWnd); + hr = pVMRControl->SetVideoClippingWindow(hMainWnd); + myprintf(L"%?erreur SetVideoClippingWindow, hr=0x%08x\n", FAILED(hr), hr); #if !USE_VMR9 - pVMRControl->SetColorKey(colorKey); + hr = pVMRControl->SetColorKey(colorKey); + myprintf(L"%?erreur SetColorKey, hr=0x%08x\n", FAILED(hr), hr); #endif { @@ -509,15 +522,16 @@ if (!pARC) return erreur(L"L'interface de contrôle du ratio d'aspect n'est pas disponible", E_NOINTERFACE); - pARC->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX); + hr = pARC->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX); + myprintf(L"%?erreur SetAspectRatioMode, hr=0x%08x\n", FAILED(hr), hr); } - if (pVideoCodec != NULL) { hr = connect_filters(pVideoCodec, pVMR); if (FAILED(hr)) { // Ici, on affiche l'erreur mais on ne quitte pas (ça laisse la possibilité d'enregistrer) affiche_erreurs(L"Impossible de connecter le codec vidéo au VMR.\nC'est probablement l'overlay qui n'est pas disponible.\n\nVeuillez le libérer et relancer l'application", hr); + hr = S_OK; } } else { @@ -525,15 +539,11 @@ return hr; } - hr = pControl->Run(); - - return hr; + return graph_Run(); } static HRESULT render_son(IMpeg2Demultiplexer * pMpeg2Demux) { - CComPtr pSoundPin; - AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_Audio; am.subtype = MEDIASUBTYPE_MPEG2_AUDIO; @@ -556,7 +566,9 @@ wfm.wBitsPerSample = 16; wfm.cbSize = 0; + CComPtr pSoundPin; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"son", &pSoundPin); + if (FAILED(hr)) return erreur(L"La broche audio MPEG2 n'a pas pu être créée", hr); @@ -566,23 +578,11 @@ return hr; // le décodeur audio - hr = get_filter(MEDIATYPE_Audio, MEDIASUBTYPE_MPEG2_AUDIO, filtreAudio, pAudioCodec); + hr = get_and_add_codec(filtreAudio, MEDIATYPE_Audio, MEDIASUBTYPE_MPEG2_AUDIO, + L"audio MPEG2", pAudioCodec); if (SUCCEEDED(hr)) { - - myprintf(L"ajout audio\n"); - - hr = pGraph->AddFilter(pAudioCodec, filtreAudio); - + hr = connect_pin_to_filter(pSoundPin, pAudioCodec); if (FAILED(hr)) - return erreur(L"Le codec audio MPEG2 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAudio); - - CComPtr pPinEntree; - - hr = cherche_pin(pAudioCodec, PINDIR_INPUT, pPinEntree); - if (SUCCEEDED(hr)) - hr = pGraph->ConnectDirect(pSoundPin, pPinEntree, NULL); - - if (FAILED(hr)) return erreur(L"Impossible de connecter le démultiplexeur au codec audio MPEG2 \"%s\"", hr, filtreAudio); hr = connect_filters(pAudioCodec, pDSound); @@ -603,7 +603,6 @@ static HRESULT render_ac3(IMpeg2Demultiplexer * pMpeg2Demux) { - CComPtr pAc3Pin; AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_Audio; @@ -627,8 +626,9 @@ wfm.wBitsPerSample = 16; wfm.cbSize = 0; - + CComPtr pAc3Pin; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"ac3", &pAc3Pin); + if (FAILED(hr)) return erreur(L"La broche audio AC3 n'a pas pu être créée", hr); @@ -638,29 +638,16 @@ return hr; // le décodeur ac3 - hr = get_filter(MEDIATYPE_Audio, MEDIASUBTYPE_DOLBY_AC3, filtreAc3, pAc3Codec); + hr = get_and_add_codec(filtreAc3, MEDIATYPE_Audio, MEDIASUBTYPE_DOLBY_AC3, + L"audio AC3", pAc3Codec); if (SUCCEEDED(hr)) { - - myprintf(L"ajout ac3\n"); - - hr = pGraph->AddFilter(pAc3Codec, filtreAc3); - + hr = connect_pin_to_filter(pAc3Pin, pAc3Codec); if (FAILED(hr)) - return erreur(L"Le codec audio AC3 \"%s\" n'a pas pu être inséré dans le graphe", hr, filtreAc3); - - CComPtr pPinEntree; - - hr = cherche_pin(pAc3Codec, PINDIR_INPUT, pPinEntree); - if (SUCCEEDED(hr)) - hr = pGraph->ConnectDirect(pAc3Pin, pPinEntree, NULL); - - if (FAILED(hr)) return erreur(L"Impossible de connecter le démultiplexeur au codec AC3 \"%s\"", hr, filtreAc3); hr = connect_filters(pAc3Codec, pDSoundAc3); if (FAILED(hr)) return erreur(L"Impossible de connecter le Codec audio AC3 \"%s\" au filtre de rendu DirectSound", hr, filtreAc3); - } else { hr = pGraph->RenderEx(pAc3Pin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL); if (FAILED(hr)) @@ -676,7 +663,6 @@ static HRESULT render_psi(IMpeg2Demultiplexer * pMpeg2Demux) { - CComPtr pDataPin; AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_MPEG2_SECTIONS; @@ -690,7 +676,9 @@ am.cbFormat = 0; am.pbFormat = NULL; + CComPtr pDataPin; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"data", &pDataPin); + if (FAILED(hr)) { erreur(L"La broche PSI n'a pas pu être créée", hr); return hr; @@ -713,12 +701,7 @@ return hr; } - CComPtr pPinEntree; - - hr = cherche_pin(pPSIFilter, PINDIR_INPUT, pPinEntree); - if (SUCCEEDED(hr)) - hr = pGraph->ConnectDirect(pDataPin, pPinEntree, NULL); - + hr = connect_pin_to_filter(pDataPin, pPSIFilter); if (FAILED(hr)) return erreur(L"Impossible de connecter le démultiplexeur au filtre PSI", hr); } @@ -728,7 +711,6 @@ static HRESULT render_epgfilter(IMpeg2Demultiplexer * pMpeg2Demux) { - CComPtr pEpgPin; AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_MPEG2_SECTIONS; @@ -742,7 +724,9 @@ am.cbFormat = 0; am.pbFormat = NULL; + CComPtr pEpgPin; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"epg", &pEpgPin); + if (FAILED(hr)) { erreur(L"La broche EPG n'a pas pu être créée", hr); return hr; @@ -759,16 +743,9 @@ if (FAILED(hr)) return erreur(L"Le filtre EPG n'a pas pu être ajouté au graphe", hr); - CComPtr pPinEntree; - - hr = cherche_pin(pEPGFilter, PINDIR_INPUT, pPinEntree); + hr = connect_pin_to_filter(pEpgPin, pEPGFilter); if (FAILED(hr)) - return erreur(L"La broche d'entrée EPG n'a pas été trouvée", hr); - - hr = pGraph->ConnectDirect(pEpgPin, pPinEntree, NULL); - - if (FAILED(hr)) - return erreur(L"La broche d'entrée EPG n'a pas pu être connectée", hr); + return erreur(L"Impossible de connecter le démultiplexeur au filtre EPG", hr); } CComQIPtr pMapEpg(pEpgPin); @@ -784,8 +761,6 @@ static HRESULT render_pmtfilter(IMpeg2Demultiplexer * pMpeg2Demux) { - CComPtr pPmtPin; - AM_MEDIA_TYPE am; am.majortype = MEDIATYPE_MPEG2_SECTIONS; am.subtype = MEDIASUBTYPE_DVB_SI; @@ -798,6 +773,7 @@ am.cbFormat = 0; am.pbFormat = NULL; + CComPtr pPmtPin; HRESULT hr = pMpeg2Demux->CreateOutputPin(&am, L"pmt", &pPmtPin); if (FAILED(hr)) @@ -815,17 +791,9 @@ if (FAILED(hr)) return erreur(L"Le filtre PMT n'a pas pu être ajouté au graphe", hr); - CComPtr pPinEntree; - - hr = cherche_pin(pPMTFilter, PINDIR_INPUT, pPinEntree); + hr = connect_pin_to_filter(pPmtPin, pPMTFilter); if (FAILED(hr)) - return erreur(L"La broche d'entrée PMT n'a pas été trouvée", hr); - - hr = pGraph->ConnectDirect(pPmtPin, pPinEntree, NULL); - - if (FAILED(hr)) - return erreur(L"La broche d'entrée PMT n'a pas pu être connectée", hr); - + return erreur(L"Impossible de connecter le démultiplexeur au filtre PMT", hr); } hr = pPmtPin.QueryInterface(&pMapPmt); @@ -868,6 +836,37 @@ return hr; } +// Mise en route du graphe : +HRESULT graph_Run() +{ + CComQIPtr pControl(pGraph); + + if (!pControl) + return E_NOINTERFACE; + return pControl->Run(); +} + +// Arrêt du graphe : +HRESULT graph_Stop() +{ + CComQIPtr pControl(pGraph); + + if (!pControl) + return E_NOINTERFACE; + return pControl->Stop(); +} + +// Interrogation de l'état du graphe : +OAFilterState graph_GetState() +{ + CComQIPtr pControl(pGraph); + OAFilterState state; + + if (!pControl || FAILED(pControl->GetState(1500, &state))) + return -1; + return state; +} + HRESULT build_graph(void) { int res; @@ -1007,14 +1006,7 @@ return hr; } - // derniers trucs - - hr = pGraph.QueryInterface(&pControl); - if (FAILED(hr)) - return hr; - - hr = pControl->Run(); - - return hr; + // mise en route + return graph_Run(); } Modifié: trunk/graph.h =================================================================== --- trunk/graph.h 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/graph.h 2008-11-20 12:15:06 UTC (rev 141) @@ -30,9 +30,20 @@ #include HRESULT build_graph(void); // retourne S_OK = pas d'erreur, != S_OK = erreur + void clean_dshow(void); + HRESULT init_vmr(void); +// Mise en route du graphe : +HRESULT graph_Run(); + +// Arrêt du graphe : +HRESULT graph_Stop(); + +// Interrogation de l'état du graphe : +OAFilterState graph_GetState(); + extern CComPtr pMpeg2Data; extern CComPtr pGraph; Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/ini.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -203,7 +203,7 @@ freq_scan.push_back(freq); } nr_multiplex++; - } while (freq.canal_no != 0 + } while (freq.canal_no != 0 && nr_multiplex <= 99); // Buffer Overflow avec des chiffres > 99 } } @@ -495,8 +495,13 @@ canal.pmt_pid = (WORD)pNode->getInt(L"PMT"); canal.pcr_pid = (WORD)pNode->getInt(L"PCR"); - canal.video_pid = (WORD)pNode->getInt(L"Video"); - canal.mpeg4_pid = (WORD)pNode->getInt(L"Video_mpeg4"); + if ((canal.video_pid = (UINT16)pNode->getInt(L"Video"))!=0) + canal.video_type = vst_MPEG2; + else if ((canal.video_pid = (UINT16)pNode->getInt(L"Video_mpeg4"))!=0) + canal.video_type = vst_H264; + else + canal.video_type = vst_Unknown; + canal.sons.nbr = (WORD)pNode->getInt(L"Nb_Son"); for (int i=0;igetInt(var); swprintf_s(var, _countof(var), L"Son%i_Type", i); - canal_son.type = (BYTE)pNode->getInt(var); + canal_son.type = (AudioStreamType)pNode->getInt(var); swprintf_s(var, _countof(var), L"Son%i_Lang", i); pNode->getStr(var, canal_son.lang, _countof(canal_son.lang)); @@ -565,12 +570,16 @@ oxml.put("PMT", canal.pmt_pid); oxml.put("PCR", canal.pcr_pid); - if (canal.video_pid > 0) + switch (canal.video_type) { + case vst_H264: + case vst_H264_encrypted: + oxml.put("Video_mpeg4", canal.video_pid); + break; + case vst_MPEG2: + default: oxml.put("Video", canal.video_pid); + } - if (canal.mpeg4_pid > 0) - oxml.put("Video_mpeg4", canal.mpeg4_pid); - oxml.put("Nb_Son", canal.sons.nbr); for (int j=0; jSetAspectRatioMode(etirer_video ? VMR_ARMODE_NONE : VMR_ARMODE_LETTER_BOX); myprintf(L"%?échec SetAspectRatioMode, hr=0x%08x\n", FAILED(hr), hr); + // TODO : essayer d'éviter que ceci produise une erreur lors de, par exemple, la + // restauration de l'affichage depuis l'état minimisé. hr = pVMRControl->SetVideoPosition(NULL, &rcDest); myprintf(L"%?échec SetVideoPosition, hr=0x%08x\n", FAILED(hr), hr); } @@ -516,9 +518,17 @@ {"deu", "Allemand"}, {"spa", "Espagnol"}, {"ita", "Italien"}, - {"por", "Portugais"} + {"por", "Portugais"}, + {"qaa", "Réservé"} }; + static const LPCSTR tblNomsAudio[] = + { + "MPG", + "AC3", + "EAC3" + }; + const Chaine & canal_courant = Canaux[ixChaineCourante]; // Récupère le nom du menu avant de l'effacer @@ -546,8 +556,8 @@ strcpy_s(langue, _countof(langue), son_courant.lang); swprintf_s(tab, _countof(tab), - L"Audio %i %S (%s)", i+1, langue, - (son_courant.type==1) ? L"AC3" : L"MPG"); + L"Audio %i %S (%S)", 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); } @@ -897,9 +907,11 @@ niData.update_tip(); } +// Changement de chaîne, sélection par index dans la table +// (mettre -1 pour désactiver la sélection de chaîne) void zappe_index(int ixChaine) { - if (change_chaine(ixChaine)==0) { + if (change_chaine(ixChaine)==S_OK) { update_all_menus(hMainWnd); update_status_bar(); @@ -947,30 +959,6 @@ update_menus(hMainWnd, 1, update_ontop_menu); } - -static int InitDshow(void) // retourne 0 = pas d'erreur, 1 = erreur -{ - HRESULT hr = build_graph(); - if (FAILED(hr)) - return hr; - - if (Canaux.size()==0) { - if (scan_dialog()!=IDOK) - return S_FALSE; - } - - if (Canaux.size() > 0) { - restaure_chaine(sidChaineConfig); - } else { - affiche_erreurs(L"Aucune chaîne n'est dans le fichier"); - update_all_menus(hMainWnd); - } - - set_volume(volumeCourant); - - return S_OK; -} - static INT_PTR CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: @@ -2112,7 +2100,7 @@ zappe_index(wID-IDM_CHAINES_BASE); } else if (wID>=IDM_PISTES_BASE && wID=IDM_STOP_RECORD_BASE && wID=0; - do { + for (;;) { HRESULT hr; if (!config_ok) { @@ -2865,37 +2843,45 @@ affiche_erreurs(L"Configuration annulée.\nLe logiciel ne peut pas être exécuté."); return -1; } - config_ok = check_config(); + if (!check_config()) { + affiche_erreurs(L"Configuration incorrecte.\nVeuillez renseigner correctement tous les champs."); + continue; + } } - if (!config_ok) { - affiche_erreurs(L"Configuration incorrecte.\nVeuillez renseigner correctement tous les champs."); - continue; - } else if (FAILED(hr = InitDshow())) { - clean_dshow(); - affiche_erreurs(L"Erreur lors de l'initialisation.\nVeuillez corriger la configuration.", hr); - config_ok = false; - - // Appeler une nouvelle fois, car certains filtres trouvent très malin d'appeler - // CoUninitialize pour se protéger des usages non autorisés : - CoInitializeEx(NULL,COINIT_MULTITHREADED); + if (SUCCEEDED(hr = build_graph())) { + if (Canaux.size()> 0 || scan_dialog()==IDOK) { + config_ok = true; + break; // tout est ok, on passe à la suite + } } - } while (!config_ok); - // On a lancé avec le paramètre demandant de masquer la fenêtre + // Retour au départ : + clean_dshow(); + affiche_erreurs(L"Erreur lors de l'initialisation.\nVeuillez corriger la configuration.", hr); + config_ok = false; + + // Appeler une nouvelle fois, car certains filtres trouvent très malin d'appeler + // CoUninitialize pour se protéger des usages non autorisés : + CoInitializeEx(NULL,COINIT_MULTITHREADED); + } + + if (!do_init_vmr()) + return -1; + + restaure_chaine(sidChaineConfig); + + set_volume(volumeCourant); + if (cmdOptions[cmd_minimize].actif) { + // On a lancé avec le paramètre demandant de masquer la fenêtre myprintf(L"minimize\n"); - if(suspend_minimized) { - debranche(); - } - } else { - if (!do_init_vmr()) + if(!suspend_minimized && !rebranche(true)) return -1; + } else { + if (ixChaine_ok(ixChaineCourante)) { + int nbChaines = (int)Canaux.size(); + long freq_courante = Canaux[ixChaineCourante].frequence; - int nbChaines = (int)Canaux.size(); - - if (ixChaineCourante>=0 && ixChaineCourante 0) && (cmd_channel <= (int)Canaux.size())){ // Vérifie que la chaine passée en paramètre est connue Modifié: trunk/main.h =================================================================== --- trunk/main.h 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/main.h 2008-11-20 12:15:06 UTC (rev 141) @@ -98,6 +98,8 @@ DWORD get_priority(); +// Changement de chaîne, sélection par index dans la table +// (mettre -1 pour désactiver la sélection de chaîne) void zappe_index(int ixChaine); /** Modifié: trunk/mpeg2defs.h =================================================================== --- trunk/mpeg2defs.h 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/mpeg2defs.h 2008-11-20 12:15:06 UTC (rev 141) @@ -76,6 +76,7 @@ operator const T & () const {return *pbeg;} operator const T * () const {return pbeg;} const T & operator () () const {return *pbeg;}; + UINT32 size() const {return UINT32(pend-pbeg);} }; template UINT8 unwrap_sequence(streamScanner limits, const T * tbl[]) @@ -480,6 +481,7 @@ // mdt_Data_Broadcast_ID = 0x66, mdt_AC3_Audio = 0x6a, + mdt_Extended_AC3_Audio = 0x7a, // mdt_Logical_Channel = 0x83 // @@ -541,8 +543,10 @@ MDescriptorTag tag() const {return static_cast(_tag);} + PUINT8 data() const + {return PUINT8(this+1);} MDescriptor * next() const - {return reinterpret_cast(PUINT8(this+1) + length);} + {return reinterpret_cast(data() + length);} template const T & as() const // Dérivation vers un type de descripteur spécifique {return *reinterpret_cast(this);} }; @@ -553,7 +557,7 @@ const T & operator () () const {return *reinterpret_cast(this+1);} streamScanner subDescrRange() const - {return streamScanner(this+1, PUINT8(this+1) + length);} + {return streamScanner(data(), data() + length);} }; // Sous-descripteur générique pour les chaînes de caractères @@ -1186,7 +1190,8 @@ {return UINT8(ac3_flags & 0xf0);} }; -struct MDescriptor_6a_unwrapper { +struct MDescriptor_6a_unwrapper +{ const MDescriptor_6a & descr; PUINT8 p_next; UINT8uw * p_ac3_type; @@ -1216,6 +1221,58 @@ } }; +/* + Syntax No. of bits Offset + ---------------------------------------------------------- + Enhanced_AC3_descriptor() { + descriptor_tag 8 0 + descriptor_length 8 1 + component_type_flag 1 2 + bsid_flag 1 2 + mainid_flag 1 2 + asvc_flag 1 2 + mixinfoexists 1 2 + substream1_flag 1 2 + substream2_flag 1 2 + substream3_flag 1 2 + if (component_type_flag)==1 { 3 + component_type 8 +0 + } + if (bsid_flag)==1 { +0 + bsid 8 +0 + } + if (mainid_flag)==1 { +0 + mainid 8 +0 + } + if (asvc_flag)==1 { +0 + asvc 8 +0 + } + if (substream1_flag)==1 { +0 + substream1 8 +0 + } + if (substream2_flag)==1 { +0 + substream2 8 +0 + } + if (substream3_flag)==1 { +0 + substream3 8 +0 + } + for (i=0;i0 ? PUINT8(this+1) : PUINT8(&flags);} UINT8 get_flags() const {return adaptation_field_length==0 ? 0 : flags;} + bool has_pcr() const + {return (get_flags() & AF_PCR_FLAG)!=0;} + const TS_PCR & get_pcr() const + {return *reinterpret_cast(beg_of_fields());} PUINT8 next() const {return PUINT8(&flags)+adaptation_field_length;} }; Modifié: trunk/parse.cpp =================================================================== --- trunk/parse.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/parse.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -78,24 +78,32 @@ case st_MPEG_1_video: //ISO_IEC_11172_2_VIDEO, MPEG-1 video streams case st_MPEG_2_video: //ISO_IEC_13818_2_VIDEO, MPEG-2 video streams lpmt_e.video_pid=pid; + lpmt_e.video_type = vst_MPEG2; break; case st_MPEG_1_audio: //ISO_IEC_11172_3_AUDIO, MPEG-1 audio streams case st_MPEG_2_audio: //ISO_IEC_13818_3_AUDIO, MPEG-2 audio streams - lpmt_e.sons.ajoute(pid, 0); + lpmt_e.sons.ajoute(pid, ast_MPEG2); break; case st_PES_private: for (; !sd; ++sd) { - if (sd().tag() == mdt_AC3_Audio) - lpmt_e.sons.ajoute(pid, 1); + switch (sd().tag()) { + case mdt_AC3_Audio: + lpmt_e.sons.ajoute(pid, ast_AC3); + break; + case mdt_Extended_AC3_Audio: + lpmt_e.sons.ajoute(pid, ast_EAC3); + break; + } } if (lpmt_e.sons.tbl[lpmt_e.sons.nbr-1].pid != pid) - lpmt_e.autr.ajoute(pid); + lpmt_e.autr.ajoute(pid, ast_Unknown); sd = se().descrRange(); // repartir du début au prochain 'for' break; case st_MPEG_4_video: //H264 - lpmt_e.mpeg4_pid=pid; + lpmt_e.video_pid=pid; + lpmt_e.video_type = vst_H264; break; } @@ -327,7 +335,7 @@ for(i = prev_size; i < Canaux.size(); i++) { const Chaine & canal = Canaux[i]; - if (canal.video_pid==0 && canal.mpeg4_pid == 0) { + if (canal.video_pid==0 && canal.video_type == vst_Unknown) { //vire cette chaine myprintf(L"Destruction [%S/%S]\n", canal.groupe, canal.nom); Canaux.erase(Canaux.begin()+(i--)); Modifié: trunk/record.cpp =================================================================== --- trunk/record.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/record.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -235,10 +235,10 @@ int grab = getFreeGrabber(); if (grab>=0) { const Chaine & canal = Canaux[ixChaine]; - NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), canal.nom, "ts"); - int video = canal.video_pid ? canal.video_pid : canal.mpeg4_pid; - ISampleGrabberCB * pCallback = NULL; - HANDLE hFile = nom_fichier.Create(); + NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), canal.nom, "ts"); + UINT16 video = canal.video_pid ; + ISampleGrabberCB * pCallback = NULL; + HANDLE hFile = nom_fichier.Create(); if (hFile != INVALID_HANDLE_VALUE) { pCallback = @@ -277,19 +277,23 @@ int grab = getFreeGrabber(); if (grab>=0) { const Chaine & canal = Canaux[ixChaine]; + + if (canal.video_type!=vst_MPEG2) // PS en MPEG2 seulement pour le moment + return 0; + NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), canal.nom, "mpg"); - int video = canal.video_pid ? canal.video_pid : canal.mpeg4_pid; - int son = canal.sons.tbl[ixSon].pid; + UINT16 video_pid = canal.video_pid; + UINT16 audio_pid = canal.sons.tbl[ixSon].pid; ISampleGrabberCB * pCallback = NULL; HANDLE hFile = nom_fichier.Create(); if (hFile != INVALID_HANDLE_VALUE) { pCallback = new CSampleGrabber( - new CCapture_PS(hFile, video, son)); + new CCapture_PS(hFile, video_pid, audio_pid)); if (pCallback!=NULL) { - myprintf(L"Enregistre PS, video=%i, audio=%i\n", video, son); + myprintf(L"Enregistre PS, video=%i, audio=%i\n", video_pid, audio_pid); enregistrements_actuels[grab].start(pCallback, ixChaine, pProg); } } else Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/recprog.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -1668,19 +1668,19 @@ int nbr_trouve = 0; // Comptage des pistes MPEG2 trouvées for(int i=0; i= 2) + if (son_type == ast_MPEG2 && ++nbr_trouve >= 2) return i; break; case audio_AC3: // audio_AC3 : on retient la 1ère piste AC3 trouvée - if (son_type == 1) + if (son_type == ast_AC3) return i; } } @@ -1756,7 +1756,7 @@ } if (!IsMinimized(hMainWnd) && suspend_minimized) - rebranche(); + rebranche(false); // Voir si la chaîne choisie n'est pas déjà en cours d'enregistrement : int grab = getGrabberChaine(ixChaine); Modifié: trunk/sbuffer.cpp =================================================================== --- trunk/sbuffer.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/sbuffer.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -47,14 +47,14 @@ } } -void StreamBuffer::put_data(const UINT8 * ptr, size_t ptr_size, bool start) +void StreamBuffer::put_data(const UINT8 * ptr, UINT32 ptr_size, bool start) { if (ptr_size > 0) { if (start) { flush(); sent = false; } - size_t newIndex = data_size+ptr_size; + UINT32 newIndex = data_size+ptr_size; if (newIndex > buf_size) { buf_size = ((newIndex/gran)+1)*gran; Modifié: trunk/sbuffer.h =================================================================== --- trunk/sbuffer.h 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/sbuffer.h 2008-11-20 12:15:06 UTC (rev 141) @@ -52,7 +52,7 @@ bool sent; // 'true' à partir du moment où "send" a été appelé (à cause d'un appel 'test' // retournant 'true'), et jusqu'à la réception d'un appel "put" avec 'start=true' public: - size_t data_size; + UINT32 data_size; StreamBuffer(size_t gr=0x200) : gran(gr), @@ -62,7 +62,7 @@ {} // Ajout de données : - void put_data(const UINT8 * ptr, size_t ptr_size, bool start=false); + void put_data(const UINT8 * ptr, UINT32 ptr_size, bool start=false); // Envoi et vidange du tampon : void flush(); Modifié: trunk/search.cpp =================================================================== --- trunk/search.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/search.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -288,14 +288,18 @@ CComPtr pDevEnum; HRESULT hr = pDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER); - if (FAILED(hr)) + if (FAILED(hr)) { + myprintf(L"remplit_tuners, ICreateDevEnum : hr=0x%08x\n", hr); return hr; + } CComPtr pEnumMoniker; hr = pDevEnum->CreateClassEnumerator(guid, &pEnumMoniker, 0); - if (FAILED(hr) || !pEnumMoniker) + if (FAILED(hr) || pEnumMoniker == NULL) { + myprintf(L"remplit_tuners, erreur création Enum Moniker : hr=0x%08x\n", hr); return hr; + } for ( CComPtr pMoniker; Modifié: trunk/settings.cpp =================================================================== --- trunk/settings.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/settings.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -365,7 +365,7 @@ const Frequence & freq = freq_scan[wParam]; wchar_t szFreq[16]; wchar_t szTemp[128]; - int last_num = Canaux.size(); + int last_num = int(Canaux.size()); swprintf_s(szFreq, _countof(szFreq), L"%03u,%03u MHz", freq.mhz/1000, freq.mhz%1000); swprintf_s(szTemp, _countof(szTemp), L"Examen canal %u à %s", freq.canal_no, szFreq); @@ -983,12 +983,12 @@ return FALSE; } -static INT_PTR renumber_dialog() +static BYTE renumber_dialog() { INT_PTR res = DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_RENUMBER), hMainWnd, RenumberDialogProc, DIALOGMODE); - return res; + return BYTE(res); } static INT_PTR CALLBACK ChannelsDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -1492,7 +1492,7 @@ **/ BYTE drivers_dialog() { - int res = + INT_PTR res = DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_CONFIG), hMainWnd, DriversDialogProc, DIALOGMODE); save_config(); // sauvegarde la configuration @@ -1506,7 +1506,7 @@ **/ BYTE scan_dialog() { - int res = + INT_PTR res = DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_SCAN), hMainWnd, ScanDialogProc, DIALOGMODE); save_config(); // sauvegarde la configuration (le nom de ville peut avoir changé) Modifié: trunk/xml.cpp =================================================================== --- trunk/xml.cpp 2008-11-16 14:59:52 UTC (rev 140) +++ trunk/xml.cpp 2008-11-20 12:15:06 UTC (rev 141) @@ -43,21 +43,23 @@ std::vector CXMLElement::getChildren() { - std::vector vect; - CComPtr pChildList; + std::vector vect; + CComPtr pChildList; - m_ele->get_childNodes(&pChildList); + if (m_ele) { + m_ele->get_childNodes(&pChildList); - if (pChildList) { - long length; - pChildList->get_length(&length); + if (pChildList) { + long length; + pChildList->get_length(&length); - for (long i=0; iget_item(i, &pNode); + pChildList->get_item(i, &pNode); - vect.push_back(new CXMLNode(pNode)); + vect.push_back(new CXMLNode(pNode)); + } } } @@ -149,7 +151,7 @@ ZeroMemory(buffer, size); getStr(nom, buffer, size); - WideCharToMultiByte(CP_ACP, 0, buffer, -1, str, size, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, buffer, -1, str, (int)size, NULL, NULL); delete buffer; } @@ -304,7 +306,7 @@ void CXMLOutput::add(LPCSTR str) { strcpy_s(&buffer[ix], _countof(buffer)-ix, str); - ix += strlen(str); + ix += (int)strlen(str); } void CXMLOutput::add(CHAR ch) From pouchintv-dev at baysse.fr Thu Nov 20 14:43:25 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Thu, 20 Nov 2008 14:43:25 +0100 Subject: [Pouchintv-dev] icones multiplex RTBF et VRT Message-ID: Bonjour, J'ai réalisé les icones des multiplex : RTBF : la Une, la Deux, la Trois, Euronews VRT : EEN, Tecknet/Canvas, Tecknet+/canvas+ Vous les trouverez en pièces jointes, cordialement, Lukoluk _________________________________________________________________ Téléphonez gratuitement à tous vos proches avec Windows Live Messenger  !  Téléchargez-le maintenant !  http://www.windowslive.fr/messenger/1.asp -------------- section suivante -------------- Une pièce jointe HTML a été nettoyée... URL: http://listes.baysse.fr/pipermail/pouchintv-dev/attachments/20081120/d749d8b7/attachment.html -------------- section suivante -------------- Une pièce jointe non texte a été nettoyée... Nom: canvas_ketnet.bmp Type: image/bmp Taille: 582 octets Desc: non disponible Url: http://listes.baysse.fr/pipermail/pouchintv-dev/attachments/20081120/d749d8b7/attachment.bin -------------- section suivante -------------- Une pièce jointe non texte a été nettoyée... Nom: canvas+_ketnet+.bmp Type: image/bmp Taille: 630 octets Desc: non disponible Url: http://listes.baysse.fr/pipermail/pouchintv-dev/attachments/20081120/d749d8b7/attachment-0001.bin -------------- section suivante -------------- Une pièce jointe non texte a été nettoyée... Nom: een.bmp Type: image/bmp Taille: 822 octets Desc: non disponible Url: http://listes.baysse.fr/pipermail/pouchintv-dev/attachments/20081120/d749d8b7/attachment-0002.bin -------------- section suivante -------------- Une pièce jointe non texte a été nettoyée... Nom: euronews.bmp Type: image/bmp Taille: 822 octets Desc: non disponible Url: http://listes.baysse.fr/pipermail/pouchintv-dev/attachments/20081120/d749d8b7/attachment-0003.bin -------------- section suivante -------------- Une pièce jointe non texte a été nettoyée... Nom: la deux.bmp Type: image/bmp Taille: 678 octets Desc: non disponible Url: http://listes.baysse.fr/pipermail/pouchintv-dev/attachments/20081120/d749d8b7/attachment-0004.bin -------------- section suivante -------------- Une pièce jointe non texte a été nettoyée... Nom: la trois.bmp Type: image/bmp Taille: 630 octets Desc: non disponible Url: http://listes.baysse.fr/pipermail/pouchintv-dev/attachments/20081120/d749d8b7/attachment-0005.bin -------------- section suivante -------------- Une pièce jointe non texte a été nettoyée... Nom: la une.bmp Type: image/bmp Taille: 678 octets Desc: non disponible Url: http://listes.baysse.fr/pipermail/pouchintv-dev/attachments/20081120/d749d8b7/attachment-0006.bin From pouchintv-dev at baysse.fr Thu Nov 20 17:29:38 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Thu, 20 Nov 2008 17:29:38 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] lolo_32 | r142 - in trunk/Icones: . Belges Message-ID: <20081120162938.C7E325F3A9@mail.baysse.fr> Author: lolo_32 Date: 2008-11-20 17:29:38 +0100 (jeu, 20 nov 2008) New Revision: 142 Added: trunk/Icones/Belges/ trunk/Icones/Belges/canvas+_ketnet+.bmp trunk/Icones/Belges/canvas_ketnet.bmp trunk/Icones/Belges/een.bmp trunk/Icones/Belges/euronews.bmp trunk/Icones/Belges/la deux.bmp trunk/Icones/Belges/la trois.bmp trunk/Icones/Belges/la une.bmp Log: * Ajout des icônes pour les chaînes Belges Property changes on: trunk/Icones/Belges ___________________________________________________________________ Nom : tsvn:logminsize + 25 Ajouté: trunk/Icones/Belges/canvas+_ketnet+.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Belges/canvas+_ketnet+.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Ajouté: trunk/Icones/Belges/canvas_ketnet.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Belges/canvas_ketnet.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Ajouté: trunk/Icones/Belges/een.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Belges/een.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Ajouté: trunk/Icones/Belges/euronews.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Belges/euronews.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Ajouté: trunk/Icones/Belges/la deux.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Belges/la deux.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Ajouté: trunk/Icones/Belges/la trois.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Belges/la trois.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp Ajouté: trunk/Icones/Belges/la une.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Belges/la une.bmp ___________________________________________________________________ Nom : svn:mime-type + image/x-ms-bmp From pouchintv-dev at baysse.fr Thu Nov 20 23:18:43 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Thu, 20 Nov 2008 23:18:43 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r143 - in trunk: . tools tools/ConditionalHeaderGenerator Message-ID: <20081120221843.5E4266EF13@mail.baysse.fr> Author: gingko Date: 2008-11-20 23:18:43 +0100 (jeu, 20 nov 2008) New Revision: 143 Added: trunk/tools/ trunk/tools/ConditionalHeaderGenerator.exe trunk/tools/ConditionalHeaderGenerator/ trunk/tools/ConditionalHeaderGenerator/ConditionalHeader.h trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.cpp trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.sln trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.vcproj trunk/tools/ConditionalHeaderGenerator/stdafx.h Modified: trunk/Pouchin TV.vcproj trunk/base.h Log: Ajout d'un système de différenciation des compilations selon que l'environnement utilisé est Visual Studio 2005 ou bien Visual C++ Express 2005. Ce système, qui m'a été fourni par un technicien de Microsoft et que j'ai ensuite adapté, est basé sur la reconnaissance du nom de l'exécutable de l'environnement (devenv.exe ou bien vcexpress.exe). La reconnaissance est faite par une petite application nommée "ConditionalHeaderGenerator.exe", qui génère un fichier "vstudio_edition.h", lui-même inclus dans "base.h". Ceci remplace la sélection manuelle dont j'avais introduit la nécessité à la r139. Ajout en annexe des sources de cet exécutable, ainsi que du projet qui l'englobe. Inclusion, d'autre part, des nouvelles icônes de chaînes dans le projet, ainsi que de quelques optimisations supplémentaires de ce projet. Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2008-11-20 16:29:38 UTC (rev 142) +++ trunk/Pouchin TV.vcproj 2008-11-20 22:18:43 UTC (rev 143) @@ -27,7 +27,7 @@ > + + @@ -1030,6 +1030,10 @@ > + + @@ -1070,6 +1074,10 @@ > + + @@ -1086,6 +1094,10 @@ > + + @@ -1201,6 +1213,40 @@ > + + + + + + + + + + + + + + + + -// Activer la définition suivante si les modèles de classes ATL ne sont -// pas disponibles sur votre ordinateur (ce qui est normalement le cas -// des utilisateurs de Visual C++ 2005 Express, sauf s'ils se sont procurés -// ces classes depuis une autre source ; ils auront dans ce cas l'erreur suivante : -// "fatal error C1083: Impossible d'ouvrir le fichier include : 'atlbase.h'" ; -// voir commentaires dans le fichier atlbase_ptvm.h) : +// 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. +// En effet, les modèles de classes ATL ne sont pas disponibles dans l'environnement +// Visual C++ 2005 Express, à moins d'avoir installé ces classes depuis une autre +// source. Voir commentaires dans le fichier atlbase_ptvm.h. -// #define DONT_HAVE_ATL_TEMPLATES +#include "vstudio_edition.h" -#ifdef DONT_HAVE_ATL_TEMPLATES +#ifndef COMPILER_EDITION_VCEXPRESS + #include +#else #include "atlbase_ptvm.h" -#else - #include #endif + #include "resource.h" // Décommenter si on veut afficher la console de debugging : Ajouté: trunk/tools/ConditionalHeaderGenerator/ConditionalHeader.h =================================================================== --- trunk/tools/ConditionalHeaderGenerator/ConditionalHeader.h (rev 0) +++ trunk/tools/ConditionalHeaderGenerator/ConditionalHeader.h 2008-11-20 22:18:43 UTC (rev 143) @@ -0,0 +1 @@ +#include "b.h" \ Pas de fin de ligne à la fin du fichier Ajouté: trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.cpp =================================================================== --- trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.cpp (rev 0) +++ trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.cpp 2008-11-20 22:18:43 UTC (rev 143) @@ -0,0 +1,219 @@ +// ConditionalHeaderGenerator.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + +BOOL ShowErr(void) +{ + DWORD dwerr = GetLastError(); + LPTSTR lpMsgBuf = NULL; + + if (ERROR_SUCCESS == dwerr) { + _tprintf(TEXT("// No errors to report\n")); + return FALSE; + } + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwerr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf, + 0, + NULL + ); + if (lpMsgBuf) { + _tprintf(TEXT("#error FAILED with code %x: %s\n"), dwerr, lpMsgBuf); + LocalFree(lpMsgBuf); + } + return TRUE; +} + +class ParentIDFinder +{ + HINSTANCE hInstLib; + HANDLE hSnapShot; + + // ToolHelp Function Pointers. + BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32); + BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32); +public: + ParentIDFinder(); + bool inited() const { + return hSnapShot!=NULL;} + DWORD GetParentID (DWORD pid); + ~ParentIDFinder(); +}; + +ParentIDFinder::ParentIDFinder() : + hInstLib(NULL), + hSnapShot(NULL), + lpfProcess32First(NULL), + lpfProcess32Next(NULL) +{ + OSVERSIONINFO osver; + HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD); + + // Check to see if were running under Windows95 or + // Windows NT. + osver.dwOSVersionInfoSize = sizeof(osver); + if (!GetVersionEx(&osver)) + return; + + if (osver.dwPlatformId != VER_PLATFORM_WIN32_NT) { + ShowErr(); + return; + } + + hInstLib = LoadLibrary(TEXT("Kernel32.DLL")); + if (hInstLib == NULL) { + ShowErr(); + return; + } + + // Get procedure addresses. + // We are linking to these functions of Kernel32 + // explicitly, because otherwise a module using + // this code would fail to load under Windows NT, + // which does not have the Toolhelp32 + // functions in the Kernel 32. + lpfCreateToolhelp32Snapshot = (HANDLE(WINAPI *)(DWORD,DWORD)) + GetProcAddress( hInstLib, "CreateToolhelp32Snapshot"); + lpfProcess32First = (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress( hInstLib, "Process32First"); + lpfProcess32Next = (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress( hInstLib, "Process32Next"); + + if (lpfProcess32Next==NULL || lpfProcess32First==NULL || lpfCreateToolhelp32Snapshot==NULL) + return; + + // Get a handle to a Toolhelp snapshot of the systems + // processes. + hSnapShot = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapShot == INVALID_HANDLE_VALUE) { + ShowErr(); + return; + } +} + +DWORD ParentIDFinder::GetParentID (DWORD pid) +{ + PROCESSENTRY32 procentry = {sizeof(PROCESSENTRY32)}; + + if (inited() && pid!=0 && lpfProcess32First(hSnapShot, &procentry)) { + // While there are processes, keep looping. + do { + if (pid==procentry.th32ProcessID) + return procentry.th32ParentProcessID; + } while (lpfProcess32Next(hSnapShot, &procentry)); + } + return 0; +} + +ParentIDFinder::~ParentIDFinder() +{ // Free the library. + if (hInstLib) + FreeLibrary(hInstLib); +} + +BOOL GetProcessName(int processID, LPTSTR * pszName) +{ + BOOL result = FALSE; + HANDLE hProcess = OpenProcess( + SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, processID ) ; + + if( hProcess != NULL ) { + // Here we call EnumProcessModules to get only the + // first module in the process this is important, + // because this will be the .EXE module for which we + // will retrieve the full path name in a second. + HMODULE hMod; + TCHAR szFileName[MAX_PATH]; + DWORD dwSize2 = 0; + + if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &dwSize2)) { + // Get Full pathname: + if (!GetModuleFileNameEx(hProcess, hMod, szFileName, _countof(szFileName))) { + szFileName[0] = 0 ; + } else { + static TCHAR szFullPathName[MAX_PATH]; + + if (!GetFullPathName(szFileName, _countof(szFullPathName), szFullPathName, pszName)) + ShowErr(); + else { + result = TRUE; + } + } + CloseHandle(hProcess); + } else { + ShowErr(); + } + } + return result; +} + +int _tmain(int argc, TCHAR * argv[]) +{ + TCHAR szAppName[64]; + long nLevelCount = 0; + + // Extraction du nom de l'application : + _tsplitpath_s(argv[0], NULL, 0, NULL, 0, + szAppName, _countof(szAppName), NULL, 0); + + if (argc>=2) { + nLevelCount = _tcstol(argv[1], NULL, 0); + } else { + + _tprintf( + TEXT("Usage : %s \n") + TEXT(" Generates a header file text on standard output for knowing if we are running\n") + TEXT(" in the Visual Studio or in the Visual C++ Express environment, by testing\n") + TEXT(" the environment process name in the parent processes tree.\n") + TEXT(" This header will define the COMPILER_EDITION_DEVENV macro in the first case,\n") + TEXT(" and the COMPILER_EDITION_VCEXPRESS in the second case.\n") + TEXT(" = expected parent process level count.\n\n"), + szAppName); + return 0; + } + + DWORD pid = GetCurrentProcessId(); + + { + ParentIDFinder cParFinder; + + // get the N x parent's process ID : + for (int nInx = 0; pid != 0 && nInx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Ajouté: trunk/tools/ConditionalHeaderGenerator/stdafx.h =================================================================== --- trunk/tools/ConditionalHeaderGenerator/stdafx.h (rev 0) +++ trunk/tools/ConditionalHeaderGenerator/stdafx.h 2008-11-20 22:18:43 UTC (rev 143) @@ -0,0 +1,9 @@ +#pragma once + +#include +#include +#include +#include +#include + +#pragma hdrstop Ajouté: trunk/tools/ConditionalHeaderGenerator.exe =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/tools/ConditionalHeaderGenerator.exe ___________________________________________________________________ Nom : svn:mime-type + application/octet-stream From pouchintv-dev at baysse.fr Thu Nov 20 23:23:19 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Thu, 20 Nov 2008 23:23:19 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] lolo_32 | r144 - in trunk: . docs Message-ID: <20081120222319.25BCD5F3E5@mail.baysse.fr> Author: lolo_32 Date: 2008-11-20 23:23:18 +0100 (jeu, 20 nov 2008) New Revision: 144 Added: trunk/Doxyfile Modified: trunk/docs/ trunk/xml.cpp trunk/xml.h Log: Doxyfile: * fichier de configuration pour Doxygen (logiciel permettant de générer la documentation du code source d'un projet) Regarder http://www.doxygen.org/index.html pour plus d'informations. xml.cpp, xml.h: * ajout de commentaires respectant Doxygen, et commentaires des fonctions/classes. docs: * ajout du dossier html aux fichiers ignorés, car c'est dans ce dossier qu'est généré la documentation par défaut. Ajouté: trunk/Doxyfile =================================================================== --- trunk/Doxyfile (rev 0) +++ trunk/Doxyfile 2008-11-20 22:23:18 UTC (rev 144) @@ -0,0 +1,1273 @@ +# Doxyfile 1.5.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +PROJECT_NAME = PouchinTVMod + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. +PROJECT_NUMBER = 0.4~svn + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. +OUTPUT_DIRECTORY = docs + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, +# Spanish, Swedish, and Ukrainian. +OUTPUT_LANGUAGE = French + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. +STRIP_FROM_PATH = . + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. +INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. +INPUT = . + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. +INPUT_ENCODING = ISO-8859-1 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +EXCLUDE = ./BaseClasses + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* +EXCLUDE_PATTERNS = */.svn/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# Qt Help Project / Namespace. +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# Qt Help Project / Virtual Folders. +QHP_VIRTUAL_FOLDER = docs + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file . +QHG_LOCATION = + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. +PREDEFINED = USE_CONSOLE=1 + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# 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" + +# 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). +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. +SEARCHENGINE = NO Property changes on: trunk/Doxyfile ___________________________________________________________________ Nom : svn:mime-type + text/plain Property changes on: trunk/docs ___________________________________________________________________ Nom : svn:ignore + html Modifié: trunk/xml.cpp =================================================================== --- trunk/xml.cpp 2008-11-20 22:18:43 UTC (rev 143) +++ trunk/xml.cpp 2008-11-20 22:23:18 UTC (rev 144) @@ -29,35 +29,55 @@ #include "xml.h" +/** + * \file + * Contient des classes pour la gestion des documents XML + **/ + +/** + * Mémorise l'élément + * + * \param[in] element élément à mémoriser + **/ CXMLElement::CXMLElement(IXMLDOMElement * element) : m_ele(element) { // myprintf(L"élément contruit\n"); } - +/** + * Ne fait rien + **/ CXMLElement::~CXMLElement() { // myprintf(L"élément détruit\n"); } +/** + * Retourne tous les enfants du noeud + * + * \return un vecteur contenant tous les enfants + **/ std::vector CXMLElement::getChildren() { - std::vector vect; - CComPtr pChildList; + std::vector vect; // Vecteur de retours + CComPtr pChildList; // Liste des enfants + // Vérifie qu'il existe des éléments if (m_ele) { + // Récupère la liste des enfants m_ele->get_childNodes(&pChildList); if (pChildList) { + // Nombre d'enfant(s) long length; pChildList->get_length(&length); for (long i=0; iget_item(i, &pNode); - vect.push_back(new CXMLNode(pNode)); } } @@ -66,47 +86,62 @@ return vect; } +/** + * Sauve un noeud + * + * \param[in] element noeud devant être sauvé + **/ CXMLNode::CXMLNode(IXMLDOMNode * element) : m_node(element) { // myprintf(L"noeud construit\n"); } - +/** + * Ne fait rien + **/ CXMLNode::~CXMLNode() { // myprintf(L"noeud détruit\n"); } +/** + * Récupère l'entier correspondant à l'élément passé en paramètre + * + * \param[in] nom nom de l'élément recherché + * \return la valeur recherchée + **/ int CXMLNode::getInt(const wchar_t * nom) { - int rep = 0; - bool trouve = false; + int rep = 0; // Valeur de retour + CComPtr pChildList; // Liste des enfants - CComPtr pChildList; - + // Récupère la liste des enfants m_node->get_childNodes(&pChildList); if (pChildList) { + // Il existe des enfants, on continue - long length; + bool trouve = false; // Élément trouvé ? + long length; // Nombre d'enfant(s) pChildList->get_length(&length); for (long i=0; i pNode; + // Récupère l'item pour comparaison pChildList->get_item(i, &pNode); BSTR bstr; pNode->get_nodeName(&bstr); + // Est-ce que l'élément actuel est le recherché ? if (wcscmp(bstr, nom) == 0) { - BSTR txt; pNode->get_text(&txt); + // mémorise l'entier trouvé rep = _wtoi(txt); SysFreeString(txt); trouve = true; - } SysFreeString(bstr); } @@ -114,85 +149,112 @@ return rep; } +/** + * Recherche la valeur textuelle associée à la clé indiquée + * + * \param[in] nom nom de la clé recherchée + * \param[out] str valeur retournée (attention, n'alloue pas de mémoire, celle-ci dois déjà être allouée) + * \param[in] size longueur du tableau de caractères (\a str) + **/ void CXMLNode::getStr(const wchar_t * nom, wchar_t * str, size_t size) { - bool found = false; - CComPtr pChildList; + CComPtr pChildList; // Liste des enfants + // Récupère les enfants m_node->get_childNodes(&pChildList); if (pChildList) { - long length; + bool found = false; // Élément trouvé ? + long length; // Nombre d'enfant(s) pChildList->get_length(&length); for (long i=0; i pNode; + CComPtr pNode; + // Récupère l'élément pour savoir si c'est le recherché pChildList->get_item(i, &pNode); BSTR bstr; pNode->get_nodeName(&bstr); + // Le nom de l'élément correspond-t-il ? if (wcscmp(bstr, nom) == 0) { - - found = true; BSTR txt; pNode->get_text(&txt); + // Mémorise la chaîne de caractères trouvée wcsncpy_s(str, size, txt, size-1); SysFreeString(txt); + found = true; } SysFreeString(bstr); } } } +/** + * Recherche la valeur textuelle associée à la clé indiquée + * + * \param[in] nom nom de la clé recherchée + * \param[out] str valeur retournée (attention, n'alloue pas de mémoire, celle-ci dois déjà être allouée) + * \param[in] size longueur du tableau de caractères (\a str) + **/ void CXMLNode::getStr(const wchar_t * nom, char * str, size_t size) { + // Utilise la fonction UNICODE pour traiter celle-ci + wchar_t *buffer = new wchar_t[size]; ZeroMemory(buffer, size); - getStr(nom, buffer, size); + this->getStr(nom, buffer, size); WideCharToMultiByte(CP_ACP, 0, buffer, -1, str, (int)size, NULL, NULL); - delete buffer; + delete [] buffer; } /** - * Récupère des enfants à partir d'un nom + * Récupère un enfant à partir de son nom + * + * \param[in] nom nom du noeud recherché + * \param[out] noeud noeud retourné si on l'a trouvé. + * Attention, ne pas oublier de libérer la mémoire une fois utilisé **/ void CXMLNode::getChildrenByName(const wchar_t *nom, CXMLNode **noeud) { - CComPtr pChildList; + CComPtr pChildList; // Liste des enfants + // Récupère les enfants m_node->get_childNodes(&pChildList); - bool found = false; - if (pChildList) { - long length; + bool found = false; // Élément trouvé ? + long length; // Nombre d'enfant(s) pChildList->get_length(&length); for (long i=0; i pNode; + // Récupère le noeud, et regarde si son nom correspond avec celui recherché pChildList->get_item(i, &pNode); - BSTR bstr; - VARIANT_BOOL bHasChild; + BSTR bstr; + VARIANT_BOOL bHasChild; - pNode->get_nodeName(&bstr); - pNode->hasChildNodes(&bHasChild); + pNode->get_nodeName(&bstr); // Récupère le nom + pNode->hasChildNodes(&bHasChild); // Regarde si il a des enfants (car sinon, c'est pas un noeud) if (wcscmp(bstr, nom) == 0 && bHasChild) { - found = true; CComPtr node; pNode->cloneNode(VARIANT_TRUE, &node); *noeud = new CXMLNode(node); + found = true; } SysFreeString(bstr); } } } +/** + * Initlialise le parseur de document XML + **/ CXMLWrapper::CXMLWrapper() { m_doc.CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER); @@ -200,12 +262,21 @@ // myprintf(L"wrapper contruit\n"); } - +/** + * Ne fait rien + **/ CXMLWrapper::~CXMLWrapper() { // myprintf(L"wrapper détruit\n"); } +/** + * Charge le document XML, et le parse + * + * \param[in] nom nom du fichier devant être ouvert + * \retval S_OK fichier chargé avec succès + * \retval S_FALSE erreur lors du chargement du fichier + **/ HRESULT CXMLWrapper::charge(const wchar_t * nom) { CComVariant var; @@ -219,13 +290,18 @@ /** * Crée un document XML à partir du contenu du paramètre + * + * \param[in] xml contenu de l'arbre XML devant être chargé. + * Attention, l'arbre doit être valide, car sinon, il ne sera pas chargé + * \retval S_OK arbre initialisé avec succès + * \retval S_FALSE erreur lors du chargement de l'arbre **/ HRESULT CXMLWrapper::charge_xml(const wchar_t *xml) { - BSTR var = SysAllocString(xml); + // Convertie le wchar_t en BSTR + BSTR var = SysAllocString(xml); + VARIANT_BOOL status; - VARIANT_BOOL status; - HRESULT hr = m_doc->loadXML(var, &status); SysFreeString(var); @@ -233,23 +309,30 @@ return hr; } +#if 0 /** * Sauvegarde le contenu du XML dans un fichier **/ -//HRESULT CXMLWrapper::sauvegarde(const wchar_t *nom) { -// VARIANT var; -// VariantInit(&var); -// -// var.vt = VT_BSTR; -// var.bstrVal = SysAllocString(nom); -// -// HRESULT hr = m_doc->save(var); -// -// VariantClear(&var); -// -// return hr; -//} +HRESULT CXMLWrapper::sauvegarde(const wchar_t *nom) { + VARIANT var; + VariantInit(&var); + var.vt = VT_BSTR; + var.bstrVal = SysAllocString(nom); + + HRESULT hr = m_doc->save(var); + + VariantClear(&var); + + return hr; +} +#endif + +/** + * Retourne la racine du DOM + * + * \return la racine du DOM actuel + **/ CXMLElement CXMLWrapper::getDocElement() { CComPtr pDOMElement; @@ -261,6 +344,12 @@ // ---------------------------------------------------------------------------- +/** + * Méthode permettant de créer un nouveau noeud, et d'incrémenter l'indentation + * + * \param[in] rf classe CXMLOutput dans laquelle le noeud doit être ajouté + * \param[in] name nom du noeud + **/ CXMLOpenChild::CXMLOpenChild(CXMLOutput & rf, LPCSTR name) : ref(rf) { @@ -270,6 +359,9 @@ ++ref.indent; } +/** + * Ferme le noeud, et décrémente l'indentation + **/ CXMLOpenChild::~CXMLOpenChild() { --ref.indent; @@ -278,20 +370,35 @@ ref.send(); } +/** + * Initialise les données de base du fichier XML, ainsi que son nom. + * Il est écrit au fur et a mesure + * + * \param[in] filename nom du fichier devant être écrit + **/ CXMLOutput::CXMLOutput(LPCWSTR filename) : fop(NULL), indent(0), ix(0) { + // Ouvre le fichier XML en écriture if (_wfopen_s(&fop, filename, L"w")!=0) { fop = NULL; return; } + // Ajoute l'encodage "iso-8859-1" add_open("?xml version=\"1.0\" encoding=\"iso-8859-1\"?"); send(); } +/** + * Retourne la chaîne de caractères parsée par vsprintf + * + * \param[in] fmt chaine définissant le style + * \param[in] ... paramètres optionels pour vsprintf + * \return la chaîne résultante + **/ LPCSTR CXMLOutput::fmt(LPCSTR fmt, ...) { static CHAR tmp_str[32]; @@ -303,18 +410,31 @@ return tmp_str; } +/** + * Ajoute une chaîne de caractères à la suite du buffer + * + * \param[in] str chaîne de caractères à concaténer + **/ void CXMLOutput::add(LPCSTR str) { strcpy_s(&buffer[ix], _countof(buffer)-ix, str); ix += (int)strlen(str); } +/** + * Ajoute un caractère à la suite du buffer + * + * \param[in] ch caractère à ajouter + **/ void CXMLOutput::add(CHAR ch) { if (ix<_countof(buffer)-1) buffer[ix++] = ch; } +/** + * Ajoute des tabulations devant la ligne + **/ void CXMLOutput::add_indent() { ix = 0; @@ -322,6 +442,11 @@ add('\t'); } +/** + * Ajoute une chaine de caractère, mais en la faisant précéder de '<' et suivre de '>'. + * + * \param[in] str chaine de caractères à ajouter + **/ void CXMLOutput::add_open(LPCSTR str) { add_indent(); @@ -330,6 +455,12 @@ add('>'); } +/** + * Ajoute une chaine de caractère, mais en la faisant précéder de ''. + * C'est donc l'ajout d'une balise fermante + * + * \param[in] str chaine de caractères à ajouter + **/ void CXMLOutput::add_close(LPCSTR str) { add("'); } +/** + * Écrit la ligne dans le fichier XML + * + * \retval EOF en cas d'erreur, ou si le fichier n'a pas pu être ouvert précédement + * \retval "valeur positive" en cas de succès + **/ int CXMLOutput::send() { add("\n"); // ajoute aussi le zéro terminateur - ix=0; - return fop ? fputs(buffer, fop) : -1; + ix=0; // Réinitialise le nombre de caractères de la ligne à 0 + return fop ? fputs(buffer, fop) : EOF; } +/** + * Stocke la chaine passée dans un nouvel élément + * + * \param[in] name nom de l'élément devant être créé + * \param[in] str valeur de l'élément. + On remplace tout de même les caractères '&', '<' et '>' par des valeurs sûres + * \return la valeur de send() + **/ int CXMLOutput::put(LPCSTR name, LPCSTR str) { CHAR ch; @@ -362,6 +507,13 @@ return send(); } +/** + * Stocke l'entier passé dans un nouvel élément + * + * \param[in] name nom de l'élément + * \param[in] val valeur à enregistrer + * \return la valeur de send() + **/ int CXMLOutput::put(LPCSTR name, int val) { CHAR str[16]; @@ -370,6 +522,9 @@ return put(name, str); } +/** + * Ferme le fichier XML + **/ CXMLOutput::~CXMLOutput() { if (fop) Modifié: trunk/xml.h =================================================================== --- trunk/xml.h 2008-11-20 22:18:43 UTC (rev 143) +++ trunk/xml.h 2008-11-20 22:23:18 UTC (rev 144) @@ -30,9 +30,13 @@ #include #include +/** + * Classe définissant un noeud du DOM + **/ class CXMLNode { private: + /// Noeud du DOM CComPtr m_node; public: @@ -47,9 +51,13 @@ void getChildrenByName(const wchar_t *nom, CXMLNode **noeud); }; +/** + * Classe définissant un élément du DOM + **/ class CXMLElement { private: + /// Élément du DOM CComPtr m_ele; public: @@ -60,9 +68,13 @@ }; +/** + * Classe utilisée pour faciliter l'ouverture des fichiers XML + **/ class CXMLWrapper { private: + /// Document DOM complet CComPtr m_doc; public: CXMLWrapper(); @@ -80,14 +92,22 @@ // ---------------------------------------------------------------------------- -// Génération d'un fichier de sortie XML : +/** + * Génération d'un fichier de sortie XML + **/ class CXMLOutput { - friend class CXMLOpenChild; - FILE * fop; - CHAR buffer[512]; - int indent; - int ix; +private: + /// On définit la classe CXMLOpenChild comme ami + friend class CXMLOpenChild; + /// Fichier devant être écrit + FILE * fop; + /// Buffer d'écriture + CHAR buffer[512]; + /// Identation du fichier XML + int indent; + /// Position dans le buffer + int ix; // (méthodes à usage interne) void add(LPCSTR str); @@ -100,6 +120,11 @@ public: CXMLOutput(LPCWSTR filename); // (constructeur ouvrant le fichier) + /** + * Indique si le fichier a pu être ouvert + * + * \retval true si le fichier est ouvert + **/ bool opened() const // 'true' si le fichier est ouvert {return fop!=NULL;} int put(LPCSTR name, int val); // Ajout d'un entier @@ -112,9 +137,12 @@ // la fermeture est assurée par le destructeur. class CXMLOpenChild { +private: + /// Référence sur la classe CXMLOutput utilisée CXMLOutput & ref; - CHAR str[32]; // sauvegarde du nom de la catégorie + /// sauvegarde du nom de la catégorie + CHAR str[32]; public: CXMLOpenChild(CXMLOutput & rf, LPCSTR name); - ~CXMLOpenChild(); // (le destructeur ferme l'enfant) + ~CXMLOpenChild(); // (le destructeur ferme l'enfant) }; From pouchintv-dev at baysse.fr Fri Nov 28 12:06:48 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Fri, 28 Nov 2008 12:06:48 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r145 - in trunk: . BaseClasses tools/ConditionalHeaderGenerator Message-ID: <20081128110648.5A3836EEB1@mail.baysse.fr> Author: gingko Date: 2008-11-28 12:06:47 +0100 (ven, 28 nov 2008) New Revision: 145 Added: trunk/BaseClasses/Doxyfile Removed: trunk/tools/ConditionalHeaderGenerator/ConditionalHeader.h trunk/tools/ConditionalHeaderGenerator/stdafx.h Modified: trunk/Doxyfile trunk/Pouchin TV.vcproj trunk/atlbase_ptvm.h trunk/base.cpp trunk/base.h trunk/graph.cpp trunk/graph.h trunk/ini.cpp trunk/main.cpp trunk/main.h trunk/search.cpp trunk/search.h trunk/settings.cpp trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.cpp trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.vcproj trunk/version.cmd Log: Création d'objets en remplacement des fonctions "search_filters", "get_filter", "remplit_tuners" et "get_tuner". Ces fonctions sont respectivement remplacées par les classes "CSearchByCategory_FillCombo", "CSearchByType_Get", "CSearchByCategory_FillCombo" et "CSearchByCategory_Get". Déplacement de la variable de configuration "exact_match" à côté des données que cette variable modifie (à savoir les noms des codecs). Ajustement de certaines chaînes de caractères et déclarations de variables de chaînes pour les rendre conformes à la spécification "TCHAR", avec dans l'idée d'ensuite généraliser progressivement ce principe et arriver à obtenir, dans un futur proche, un code source de PouchinTV Mod qui puisse être compilé indifféremment en mode Unicode, ANSI ou DBCS. Suppression de fichiers inutiles dans tools\ConditionalHeaderGenerator. Déplacement de l'appel de "ConditionalHeaderGenerator" dans "version.cmd", et ajout d'un test conditionnel sur cet appel (pour éviter que la régénération systématique de "vstudio_edition.h" conduise à la régénération systématique de tout le projet à chaque fois qu'une nouvelle compilation est requise. Optimisation du fichier Doxyfile (en particulier, changement du formatage des messages d'avertissement pour que Visual Studio puisse les gérer, et gestion non récursive du répertoire inclus). Inclusion de ce fichier Doxyfile dans le projet, et configuration pour exécution post-génération (mais en laissant celle-ci désactivée, considérant que tout le monde n'aura pas nécessairement installé Doxyfile et graphViz). Ajout d'un autre fichier Doxyfile pour le répertoire "BaseClasses". Ajout de commentaires compatibles "Doxyfile" à certains endroits. Ajouté: trunk/BaseClasses/Doxyfile =================================================================== --- trunk/BaseClasses/Doxyfile (rev 0) +++ trunk/BaseClasses/Doxyfile 2008-11-28 11:06:47 UTC (rev 145) @@ -0,0 +1,1277 @@ +# Doxyfile 1.5.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +PROJECT_NAME = BaseClasses + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. +PROJECT_NUMBER = 0 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. +OUTPUT_DIRECTORY = ..\docs\BaseClasses + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, +# Spanish, Swedish, and Ukrainian. +OUTPUT_LANGUAGE = French + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. +STRIP_FROM_PATH = . + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. +INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) +WARN_FORMAT = "$file($line) : $text" +# Note : le format ci-dessus est compatible Visual Studio 2005, et permet +# de se rendre directement à l'emplacement visé si on double-clique sur le +# message d'erreur (à condition d'avoir intégré Doxygen en tant qu'événement +# post-génération dans le projet). + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. +INPUT = . + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. +INPUT_ENCODING = ISO-8859-1 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* +EXCLUDE_PATTERNS = */.svn/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# Qt Help Project / Namespace. +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# Qt Help Project / Virtual Folders. +QHP_VIRTUAL_FOLDER = docs + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file . +QHG_LOCATION = + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. +PREDEFINED = USE_CONSOLE=1 + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# 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" + +# 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). +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +MAX_DOT_GRAPH_DEPTH = 1000 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. +SEARCHENGINE = NO Modifié: trunk/Doxyfile =================================================================== --- trunk/Doxyfile 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/Doxyfile 2008-11-28 11:06:47 UTC (rev 145) @@ -115,6 +115,12 @@ # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO +# Note : si, à la génération, vous obtenez des erreurs multiples de type +# "Error opening map file *.map for inclusion in the docs!", ne cherchez pas à +# changer l'option SHORT_NAMES ainsi qu'il est parfois ndiqué sur le Net. +# Contentez-vous d'effacer le contenu du répertoire "docs/html" et refaites la +# génération de la documentation Doxyfile. Voir bug Doxygen 525273, ici : +# http://bugzilla.gnome.org/show_bug.cgi?id=525273 # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style @@ -464,7 +470,11 @@ # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) -WARN_FORMAT = "$file:$line: $text" +WARN_FORMAT = "$file($line) : $text" +# Note : le format ci-dessus est compatible Visual Studio 2005, et permet +# de se rendre directement à l'emplacement visé si on double-clique sur le +# message d'erreur (à condition d'avoir intégré Doxygen en tant qu'événement +# post-génération dans le projet). # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written @@ -499,12 +509,12 @@ # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. -RECURSIVE = YES +RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = ./BaseClasses +EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/Pouchin TV.vcproj 2008-11-28 11:06:47 UTC (rev 145) @@ -27,7 +27,7 @@ > + + Modifié: trunk/atlbase_ptvm.h =================================================================== --- trunk/atlbase_ptvm.h 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/atlbase_ptvm.h 2008-11-28 11:06:47 UTC (rev 145) @@ -56,7 +56,7 @@ CComPtr() : p(NULL) { } - CComPtr(IU* q) : p(q) { + CComPtr(IU* q) : p(q) { if (p) p->AddRef();} CComPtr(const CComPtr & r) : p(r.p) { if (p) p->AddRef();} @@ -70,7 +70,7 @@ return p;} void Release() { IU* t=p; if (t) {p=NULL; t->Release();}} - IU* operator = (const IU* q) { + IU* operator = (const IU* q) { Release(); p=q; p->AddRef(); return p;} CComPtr & operator = (const CComPtr & r) { Release(); p=r.p; p->AddRef(); return *this;} Modifié: trunk/base.cpp =================================================================== --- trunk/base.cpp 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/base.cpp 2008-11-28 11:06:47 UTC (rev 145) @@ -31,36 +31,36 @@ HWND hMainWnd = NULL; -static LPWSTR pszErrBuf = NULL; +static LPTSTR pszErrBuf = NULL; static HRESULT lastRes = S_OK; -HRESULT erreur(LPCWSTR str, HRESULT hr, ...) +HRESULT erreur(LPCTSTR str, HRESULT hr, ...) { - WCHAR buffer[0x200]; + TCHAR buffer[0x200]; if (str) { - LPWSTR pszNewErrBuf; + LPTSTR pszNewErrBuf; va_list argptr; va_start(argptr, hr); - vswprintf_s(buffer, str, argptr); + _vstprintf_s(buffer, str, argptr); va_end(argptr); - UINT nBufLen = UINT(wcslen(buffer)+1); + UINT nBufLen = UINT(_tcslen(buffer)+1); if (pszErrBuf) { - static LPCWSTR pszEol = L"\n"; - UINT nPrevLen = UINT(wcslen(pszErrBuf)+wcslen(pszEol)); + static LPCTSTR pszEol = TEXT("\n"); + UINT nPrevLen = UINT(_tcslen(pszErrBuf)+_tcslen(pszEol)); nBufLen += nPrevLen; - pszNewErrBuf = new WCHAR[nBufLen]; - wcscpy_s(pszNewErrBuf, nBufLen, pszErrBuf); - wcscat_s(pszNewErrBuf, nBufLen, pszEol); - wcscat_s(pszNewErrBuf, nBufLen, buffer); + pszNewErrBuf = new TCHAR[nBufLen]; + _tcscpy_s(pszNewErrBuf, nBufLen, pszErrBuf); + _tcscat_s(pszNewErrBuf, nBufLen, pszEol); + _tcscat_s(pszNewErrBuf, nBufLen, buffer); delete pszErrBuf; } else { - pszNewErrBuf = new WCHAR[nBufLen]; - wcscpy_s(pszNewErrBuf, nBufLen, buffer); + pszNewErrBuf = new TCHAR[nBufLen]; + _tcscpy_s(pszNewErrBuf, nBufLen, buffer); } pszErrBuf = pszNewErrBuf; } @@ -68,13 +68,13 @@ if (FAILED(hr) && hr!=lastRes) { AMGetErrorText(hr, buffer, _countof(buffer)); - erreur(L"%s (code 0x%08x)", S_OK, buffer, hr); + erreur(TEXT("%s (code 0x%08x)"), S_OK, buffer, hr); lastRes = hr; } return hr; } -void affiche_erreurs(LPCWSTR str, HRESULT hr) +void affiche_erreurs(LPCTSTR str, HRESULT hr) { erreur(str, hr); if (pszErrBuf) { Modifié: trunk/base.h =================================================================== --- trunk/base.h 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/base.h 2008-11-28 11:06:47 UTC (rev 145) @@ -192,5 +192,5 @@ etf_minimized // minimisée (en icône ou pas) }; -HRESULT erreur(LPCWSTR str, HRESULT hr, ...); -void affiche_erreurs(LPCWSTR str, HRESULT hr=S_OK); +HRESULT erreur(LPCTSTR str, HRESULT hr, ...); +void affiche_erreurs(LPCTSTR str, HRESULT hr=S_OK); Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/graph.cpp 2008-11-28 11:06:47 UTC (rev 145) @@ -183,7 +183,7 @@ static HRESULT get_and_add_codec(LPCWSTR nom, GUID type, GUID subtype, LPCWSTR infotype, CComPtr & pFilter) { - HRESULT hr = get_filter(type, subtype, nom, pFilter); + HRESULT hr = CSearchByType_Get(type, subtype, exact_match, nom, pFilter).Do(); if (SUCCEEDED(hr)) { myprintf(L"Ajout codec %s\n", infotype); Modifié: trunk/graph.h =================================================================== --- trunk/graph.h 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/graph.h 2008-11-28 11:06:47 UTC (rev 145) @@ -29,24 +29,53 @@ #include +/** + * Construction et mise en route du graphe DirectShow + * \return Code d'erreur DirectShow + **/ HRESULT build_graph(void); // retourne S_OK = pas d'erreur, != S_OK = erreur +/** + * Arrêt du graphe avec nettoyage de toutes les ressources utilisées par celui-ci + **/ void clean_dshow(void); +/** + * Initialisation du Video Mixing Renderer + * \return Code d'erreur DirectShow + **/ HRESULT init_vmr(void); -// Mise en route du graphe : +/** + * Mise en route du graphe + * \return Code d'erreur DirectShow + **/ HRESULT graph_Run(); -// Arrêt du graphe : +/** + * Arrêt du graphe + * \return Code d'erreur DirectShow + **/ HRESULT graph_Stop(); -// Interrogation de l'état du graphe : +/** + * Traitement d'un événement du graphe + * \return Code d'erreur DirectShow + **/ +HRESULT HandleGraphEvent(); + +/** + * Interrogation de l'état du graphe + * \return Valeurs de l'énumération FILTER_STATE (strmif.h) + * \retval 0 (State_Stopped) Le graphe est arrêté + * \retval 1 (State_Paused) Le graphe est en mode "pause" + * \retval 2 (State_Running) Le graphe est en marche + **/ OAFilterState graph_GetState(); -extern CComPtr pMpeg2Data; +extern CComPtr pMpeg2Data; //!< Interface d'accès aux sections PSI -extern CComPtr pGraph; +extern CComPtr pGraph; //!< Interface d'accès global au graphe extern CComPtr pNetworkTuner; extern CComPtr pReceiverComponent; Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/ini.cpp 2008-11-28 11:06:47 UTC (rev 145) @@ -679,7 +679,7 @@ save_config_str(ini_filtre_audio, filtreAudio); save_config_str(ini_filtre_ac3, filtreAc3); save_config_str(ini_nom_ville, nomVille); - save_config_bool(ini_strict, exact_match==TRUE); + save_config_bool(ini_strict, exact_match); save_config_int(ini_chaine_courante, indexToSID(ixChaineCourante)); save_config_str(ini_rep_video, video_dir); save_config_str(ini_rep_screen, screenshots_dir); @@ -854,24 +854,24 @@ **/ bool check_config(void) { - get_tuner(KSCATEGORY_BDA_NETWORK_TUNER, nom_tuner, pNetworkTuner); + CSearchByCategory_Get(KSCATEGORY_BDA_NETWORK_TUNER, nom_tuner, pNetworkTuner).Do(); if (pNetworkTuner == NULL) { return false; } else { - int res = filtre_compat(pNetworkTuner); + CompatResult eCompat = filtre_compat(pNetworkTuner); - if (res == 1) { // PCI - get_tuner(KSCATEGORY_BDA_RECEIVER_COMPONENT, nom_receiver, pReceiverComponent); + if (eCompat == compat_Tuner) { // PCI + CSearchByCategory_Get(KSCATEGORY_BDA_RECEIVER_COMPONENT, nom_receiver, pReceiverComponent).Do(); - if (filtre_compat(pReceiverComponent) != 0) { + if (filtre_compat(pReceiverComponent) != compat_None) { return true; } else { pNetworkTuner.Release(); pReceiverComponent.Release(); return false; } - } else if (res == 2) { // USB + } else if (eCompat == compat_Receiver) { // USB return true; } else { pNetworkTuner.Release(); Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/main.cpp 2008-11-28 11:06:47 UTC (rev 145) @@ -66,6 +66,7 @@ wchar_t filtreAudio[256]; wchar_t filtreAc3[256]; wchar_t nomVille[256]; +bool exact_match; wchar_t nom_tuner[256]; wchar_t nom_receiver[256]; Modifié: trunk/main.h =================================================================== --- trunk/main.h 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/main.h 2008-11-28 11:06:47 UTC (rev 145) @@ -45,6 +45,12 @@ extern wchar_t filtreAc3[256]; extern wchar_t nomVille[256]; +/** + * Variable de configuration : + * Indique si une correspondance exacte est souhaitée dans la recherche de filtres + */ +extern bool exact_match; + extern wchar_t nom_tuner[256]; extern wchar_t nom_receiver[256]; Modifié: trunk/search.cpp =================================================================== --- trunk/search.cpp 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/search.cpp 2008-11-28 11:06:47 UTC (rev 145) @@ -26,28 +26,31 @@ */ #include "base.h" +#include "search.h" -BOOL exact_match; - // 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): struct VarStr_helper { - wchar_t str[128]; + TCHAR str[128]; VarStr_helper(const VARIANT & var); - LPCWSTR operator () () const {return str;} + LPCTSTR operator () () const {return str;} }; // Constructeur : VarStr_helper::VarStr_helper(const VARIANT & var) { if (var.vt==VT_BSTR) { +#ifdef _UNICODE wcscpy_s(str, _countof(str), var.bstrVal); +#else + WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, str, _countof(str), NULL, NULL); +#endif str[_countof(str)-1] = 0; // précaution - size_t len = wcslen(str); + size_t len = _tcslen(str); while (len>0 && str[--len]<=' ') str[len] = 0; @@ -55,29 +58,21 @@ str[0] = 0; } -/** - * Recherche les filtres valides : - * - MPEG2 - * - AC3 - **/ -void search_filters(GUID type, GUID subtype, HWND hItm) +CSearchByType::CSearchByType(GUID type, GUID subtype, bool bExactMatch) : + hr(E_FAIL) { - CComPtr pMapper; - - HRESULT hr = pMapper.CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC); + hr = pMapper.CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC); if (FAILED(hr)) { - myprintf(L"search_filters, 1, hr=0x%08x\n", hr); + myprintf(TEXT("CSearchByType, CoCreateInstance, hr=0x%08x\n"), hr); return; } GUID arrayInTypes[2] = {type, subtype}; - CComPtr pEnum; - hr = pMapper->EnumMatchingFilters( &pEnum, 0, // Reserved. - exact_match, // Use exact match? + bExactMatch, // Use exact match? MERIT_DO_NOT_USE+1, // Minimum merit. TRUE, // At least one input pin? 1, // Number of major type/subtype pairs for input. @@ -91,89 +86,20 @@ NULL, // Output medium. NULL); // Output pin category. - if (FAILED(hr)) { - myprintf(L"search_filters, 2, hr=0x%08x\n", hr); + myprintf(TEXT("CSearchByType, EnumMatchingFilters, hr=0x%08x\n"), hr); return; } - - // Enumerate the monikers. - ULONG cFetched; - - for ( - CComPtr pMoniker; - pEnum->Next(1, &pMoniker, &cFetched)==S_OK; - pMoniker.Release() - ) { - CComPtr pPropBag; - - if (FAILED(hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag))) - continue; - - // To retrieve the friendly name of the filter, do the following: - CComVariant varName; - - if (FAILED(hr = pPropBag->Read(L"FriendlyName", &varName, 0))) - continue; - // Display the name in your UI somehow. - VarStr_helper vstr(varName); - //myprintf(L"filtre : %s\n", vstr); - - SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)vstr()); - } } - -HRESULT get_filter(GUID type, GUID subtype, LPCWSTR nom, CComPtr & pFilter) +HRESULT CSearchByType::Do() { - myprintf(L"get_filter: type={%08x-%04x-%04x-%012x}\n", type.Data1, type.Data2, type.Data3, type.Data4); - myprintf(L"\tsubtype={%08x-%04x-%04x-%012x}\n", subtype.Data1, subtype.Data2, subtype.Data3, subtype.Data4); - myprintf(L"\tnom=%s\n", nom); - - pFilter.Release(); // au cas où - - CComPtr pMapper; - - HRESULT hr = pMapper.CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC); - if (FAILED(hr)) { - myprintf(L"get_filter, 1, hr=0x%08x\n", hr); - return hr; - } - - GUID arrayInTypes[2]; - arrayInTypes[0] = type; - arrayInTypes[1] = subtype; - - CComPtr pEnum; - - hr = pMapper->EnumMatchingFilters( - &pEnum, - 0, // Reserved. - exact_match, // Use exact match? - MERIT_DO_NOT_USE+1, // Minimum merit. - TRUE, // At least one input pin? - 1, // Number of major type/subtype pairs for input. - arrayInTypes, // Array of major type/subtype pairs for input. - NULL, // Input medium. - NULL, // Input pin category. - FALSE, // Must be a renderer? - TRUE, // At least one output pin? - 0, // Number of major type/subtype pairs for output. - NULL, // Array of major type/subtype pairs for output. - NULL, // Output medium. - NULL); // Output pin category. - - if (FAILED(hr)) { - myprintf(L"get_filter, 2, hr=0x%08x\n", hr); - return hr; - } - // Enumerate the monikers. ULONG cFetched; for ( CComPtr pMoniker; - !pFilter && pEnum->Next(1, &pMoniker, &cFetched)==S_OK; + pEnum->Next(1, &pMoniker, &cFetched)==S_OK; pMoniker.Release() ) { CComPtr pPropBag; @@ -187,11 +113,13 @@ if (FAILED(hr = pPropBag->Read(L"FriendlyName", &varName, 0))) continue; + // Display the name in your UI somehow. VarStr_helper vstr(varName); - if (wcscmp(vstr(), nom)==0) - hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); + hr = ApplyOne(pMoniker, vstr()); + if (FAILED(hr) || hr==S_FALSE) + break; } return hr; @@ -200,35 +128,37 @@ // 1er pin non connecté HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, CComPtr & result) { + myprintf(TEXT("** cherche_pin\n")); CComPtr pEnumPins; HRESULT hr = pFilter->EnumPins(&pEnumPins); if (FAILED(hr)) { - myprintf(L"cherche_pin, 1, hr=0x%08x\n", hr); + myprintf(TEXT("cherche_pin, 1, hr=0x%08x\n"), hr); return hr; } for ( - CComPtr curpin; - (hr = pEnumPins->Next(1, &curpin, NULL))==S_OK; - curpin.Release() + CComPtr pPin; + (hr = pEnumPins->Next(1, &pPin, NULL))==S_OK; + pPin.Release() ) { PIN_DIRECTION direction; - curpin->QueryDirection(&direction); + pPin->QueryDirection(&direction); if (direction == dir) { #ifdef _DEBUG + // write_pin_info(pPin); CComPtr connected; - curpin->ConnectedTo(&connected); + pPin->ConnectedTo(&connected); if (!connected) { - result = curpin; + result = pPin; break; } #else - result = curpin; + result = pPin; break; #endif } @@ -237,13 +167,12 @@ return !result ? E_FAIL : hr; } -// 0 pas compat, 1 tuner, 2 receiver -int filtre_compat(CComPtr & pFilter) +CompatResult filtre_compat(CComPtr & pFilter) { - int res = 0; + CompatResult eCompat = compat_None; if (!pFilter) - return res; + return eCompat; CComPtr pEnumPins; @@ -251,7 +180,7 @@ for ( CComPtr pPin; - res==0 && pEnumPins->Next(1, &pPin, NULL)==S_OK; + eCompat==compat_None && pEnumPins->Next(1, &pPin, NULL)==S_OK; pPin.Release() ) { PIN_DIRECTION dir; @@ -266,12 +195,12 @@ AM_MEDIA_TYPE * am; - while (res==0 && (pEnumMedia->Next(1, &am, NULL))==S_OK) { + while (eCompat==compat_None && (pEnumMedia->Next(1, &am, NULL))==S_OK) { if (am->majortype == MEDIATYPE_Stream) { if (am->subtype == KSDATAFORMAT_TYPE_MPEG2_TRANSPORT) { - res = 1; + eCompat = compat_Tuner; } else if (am->subtype == KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT) { - res = 2; + eCompat = compat_Receiver; } } @@ -279,104 +208,60 @@ } } - return res; + return eCompat; } -HRESULT remplit_tuners(GUID guid, HWND hItm) +CSearchByCategory::CSearchByCategory(CLSID clsid) : + hr(E_FAIL) { - // Create the System Device Enumerator. - CComPtr pDevEnum; - - HRESULT hr = pDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER); + hr = pDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER); if (FAILED(hr)) { - myprintf(L"remplit_tuners, ICreateDevEnum : hr=0x%08x\n", hr); - return hr; + myprintf(TEXT("CSearchByCategory, ICreateDevEnum : hr=0x%08x\n"), hr); + return; } - CComPtr pEnumMoniker; - - hr = pDevEnum->CreateClassEnumerator(guid, &pEnumMoniker, 0); + hr = pDevEnum->CreateClassEnumerator(clsid, &pEnumMoniker, 0); if (FAILED(hr) || pEnumMoniker == NULL) { - myprintf(L"remplit_tuners, erreur création Enum Moniker : hr=0x%08x\n", hr); - return hr; + myprintf(TEXT("CSearchByCategory, erreur création Enum Moniker : hr=0x%08x\n"), hr); + return; } +} +HRESULT CSearchByCategory::Do() +{ + if (FAILED(hr)) + return hr; + for ( CComPtr pMoniker; pEnumMoniker->Next(1, &pMoniker, NULL)==S_OK; pMoniker.Release() ) { - CComPtr pFilter; + CComPtr pPropBag; - HRESULT hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter); - - if (FAILED(hr) || filtre_compat(pFilter)==0) + hr = pMoniker->BindToStorage(NULL, NULL, IID_IPropertyBag, (void **)&pPropBag); + if (FAILED(hr)) continue; - CComPtr pPropBag; + CComPtr pFilter; - if (FAILED(pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag))) + hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); + if (FAILED(hr)) continue; // To retrieve the friendly name of the filter, do the following: CComVariant varName; - if (SUCCEEDED(pPropBag->Read(L"FriendlyName", &varName, 0))) { - myprintf(L"remplit_tuner, Tuner : %s\n", varName.bstrVal); - SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)varName.bstrVal); - } - } + if (FAILED(pPropBag->Read(L"FriendlyName", &varName, 0))) + continue; - return hr; -} + VarStr_helper vstr(varName); -// renvoie le filtre à partir du nom -HRESULT get_tuner(GUID guid, LPCWSTR nom, CComPtr & pFilter) -{ - pFilter.Release(); + hr = ApplyOne(pFilter, vstr()); - myprintf(L"get_tuner: guid={%08x-%04x-%04x-%012x}, nom=%s\n", guid.Data1, guid.Data2, guid.Data3, guid.Data4, nom); - - // Create the System Device Enumerator. - CComPtr pDevEnum; - - HRESULT hr = pDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER); - - if (FAILED(hr)) { - myprintf(L"get_tuner, ICreateDevEnum : hr=0x%08x\n", hr); - return hr; + if (FAILED(hr) || hr==S_FALSE) + break; } - - CComPtr pEnumMoniker; - - hr = pDevEnum->CreateClassEnumerator(guid, &pEnumMoniker, 0); - if (FAILED(hr) || !pEnumMoniker) { - myprintf(L"get_tuner, erreur création Enum Moniker : hr=0x%08x\n", hr); - return hr; - } - - for ( - CComPtr pMoniker; - !pFilter && pEnumMoniker->Next(1, &pMoniker, NULL)==S_OK; - pMoniker.Release() - ) { - CComPtr pPropBag; - - if (SUCCEEDED(pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag))) { - // To retrieve the friendly name of the filter, do the following: - CComVariant varName; - - if (FAILED(pPropBag->Read(L"FriendlyName", &varName, 0))) - continue; - - VarStr_helper vstr(varName); - - myprintf(L"get_tuner, Tuner : %s\n", varName.bstrVal); - if (wcscmp(vstr(), nom)==0) - hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); - } - } - return hr; } Modifié: trunk/search.h =================================================================== --- trunk/search.h 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/search.h 2008-11-28 11:06:47 UTC (rev 145) @@ -27,15 +27,278 @@ #pragma once -//IBaseFilter * search_mpeg2(IEnumMoniker *pEnumMoniker, GUID subtype, GUID format); +/** + * Macro s'insérant au milieu d'une chaîne de formatage style + * \p printf pour produire le contenu d'un objet GUID ou CLSID. Une macro + * \p GUIDPARM doit correspondre, en position, dans les arguments associés. + */ +#define GUIDFMT TEXT("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}") +/** + * Macro s'insérant dans les arguments d'une fonction de style \p printf + * pour produire le contenu d'un objet GUID ou CLSID. Doit correspondre en position + * à une macro GUIDFMT insérée dans la chaîne de formatage. + * \param[in] x Objet GUID ou CLSID dont on veut produire la sortie. + */ +#define GUIDPARM(x) x.Data1, x.Data2, x.Data3, \ + x.Data4[0],x.Data4[1],x.Data4[2],x.Data4[3], \ + x.Data4[4],x.Data4[5],x.Data4[6],x.Data4[7] + + +/** + * Recherche de la première broche non connectée d'un filtre, pour une direction donnée. + * \param[in] pFilter Interfac du filtre dans lequel la recherche s'effectue + * \param[in] dir Direction de la broche recherchée (entrée ou sortie) + * \param[out] result Interface de la broche trouvée + * \retval S_OK en cas de succès +*/ HRESULT cherche_pin(CComPtr & pFilter, PIN_DIRECTION dir, CComPtr & result); -void search_filters(GUID type, GUID subtype, HWND hItm); -HRESULT get_filter(GUID type, GUID subtype, LPCWSTR nom, CComPtr & pFilter); -HRESULT remplit_tuners(GUID guid, HWND hItm); -HRESULT get_tuner(GUID guid, LPCWSTR nom, CComPtr & pFilter); +/** + * Classe d'assistance à l'énumération de codecs ayant des + * caractéristiques données. + */ +class CSearchByType +{ + CComPtr pMapper; + CComPtr pEnum; +public: + HRESULT hr; -int filtre_compat(CComPtr & pFilter); + /** + * Constructeur : prépare l'énumération pour une paire de types donnés. + * \param[in] type CLSID pour le type + * \param[in] subtype CLSID pour le sous-type + * \param[in] bExactMatch true si correspondance exacte requise + */ + CSearchByType(GUID type, GUID subtype, bool bExactMatch); -extern BOOL exact_match; + /** + * Méthode virtuelle "pure" appelée pour chaque filtre trouvé. + * \param[in] pMoniker "Moniker" vers ce filtre + * \param[in] pszName nom du filtre + * \retval S_OK si l'énumération doit ensuite continuer + * \retval S_FALSE si l'énumération doit s'arrêter (par exemple parce qu'on + * a trouvé ce qu'on cherchait) + */ + virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCTSTR pszName) = 0; + + /** + * Application de la méthode virtuelle \p ApplyOne à chaque filtre trouvé. + * \return Code d'erreur DirectShow + */ + HRESULT Do(); +}; + +/** + * Classe d'assistance au remplissage d'une liste déroulante + * avec une liste de codecs ayant des caractéristiques données. + */ +class CSearchByType_FillCombo : public CSearchByType +{ + HWND hItem; +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. + * \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. + */ + CSearchByType_FillCombo(GUID type, GUID subtype, bool bExactMatch, HWND hItm) : + CSearchByType(type, subtype, bExactMatch), + hItem(hItm) + {} + + /** + * Implémentation de méthode virtuelle appelée pour chaque codecs 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); + return S_OK; + } +}; + +/** + * Classe d'assistance à la recherche d'un codec ayant des caractéristiques + * données, à partir de son nom, + */ +class CSearchByType_Get : public CSearchByType +{ + LPCTSTR pszSearch; + CComPtr & pFilter; +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] type CLSID pour le type + * \param[in] subtype CLSID pour le sous-type + * \param[in] bExactMatch true si correspondance exacte requise + * \param[in] pszSrch Nom du codec recherché. + * \param[out] pFltr Pointeur ATL destiné recevoir l'interface du filtre trouvé, s'il existe. + */ + CSearchByType_Get(GUID type, GUID subtype, bool bExactMatch, LPCTSTR pszSrch, CComPtr & pFltr) : + CSearchByType(type, subtype, bExactMatch), + pszSearch(pszSrch), + pFilter(pFltr) + { + myprintf( + TEXT("CSearchByType_Get: type=") GUIDFMT TEXT("\n\tsubtype=") GUIDFMT TEXT("\n\tnom=%s\n"), + GUIDPARM(type), GUIDPARM(subtype), pszSrch); + + pFltr.Release(); // précaution + } + + /** + * Implémentation de méthode virtuelle appelée pour chaque filtre trouvé. + * \param[in] pMoniker "Moniker" vers ce filtre + * \param[in] pszName nom du codec + * \retval true tant que le codec n'a pas été trouvé + * \retval false quand le codec a été trouvé, afin d'arrêter la recherche + */ + virtual HRESULT ApplyOne(CComPtr & pMoniker, LPCTSTR pszName) + { + if (_tcscmp(pszName, pszSearch)==0) { + hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter); + return S_FALSE; + } + + return S_OK; + } +}; + +/** + * Listes des valeurs retournées par \p filtre_compat + */ +enum CompatResult +{ + compat_None, //!< 0 pas compat + compat_Tuner, //!< 1 tuner (PCI ?) + compat_Receiver //!< 2 receiver (USB ?) +}; + +/** + * Recherche les compatibilités sur les broches de sortie d'un filtre BDA + * \param[in] pFilter Filtre à tester + * \retval compat_None Aucune compatibilité + * \retval compat_Tuner Compatibilité Tuner / PCI / KSDATAFORMAT_TYPE_MPEG2_TRANSPORT + * \retval compat_Receiver Compatibilité Receiver / USB / KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT + */ +CompatResult filtre_compat(CComPtr & pFilter); + +/** + * Classe d'assistance à l'énumération des filtres dans une catégorie donnée. + */ +class CSearchByCategory +{ + CComPtr pDevEnum; + CComPtr pEnumMoniker; + HRESULT hr; +public: + + /** + * Constructeur : prépare l'énumération pour une catégorie donnée. + * \param[in] clsid CLSID pour la catégorie + */ + CSearchByCategory(CLSID clsid); + + /** + * Méthode virtuelle "pure" appelée pour chaque filtre trouvé. + * \param[in] pszName nom du filtre + * \param[in] pCurFltr interface vers ce filtre + * \retval S_OK si l'énumération doit ensuite continuer + * \retval S_FALSE si l'énumération doit s'arrêter (par exemple parce qu'on + * a trouvé ce qu'on cherchait) + */ + virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCTSTR pszName) = 0; + + /** + * Application de la méthode virtuelle \p ApplyOne à chaque filtre trouvé. + * \return Code d'erreur DirectShow + */ + HRESULT Do(); +}; + +/** + * Classe d'assistance au remplissage d'une liste déroulante + * avec une liste de filtres disponibles. + */ +class CSearchByCategory_FillCombo : public CSearchByCategory +{ + HWND hItem; +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. + */ + CSearchByCategory_FillCombo(CLSID clsid, HWND hItm) : + CSearchByCategory(clsid), + hItem(hItm) + {} + + /** + * Implémentation de méthode virtuelle appelée pour chaque filtre trouvé. + * \param[in] pCurFltr interface 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 & pCurFltr, LPCTSTR pszName) + { + if (filtre_compat(pCurFltr)!=compat_None) { + myprintf(TEXT("CSearchByCategory_FillCombo : %s\n"), pszName); + SendMessage(hItem, CB_ADDSTRING, 0, (LPARAM)pszName); + } + return S_OK; + } +}; + +/** + * Classe d'assistance à la recherche d'un filtre à partir de son nom, dans une catégorie donnée. + */ +class CSearchByCategory_Get : public CSearchByCategory +{ + LPCTSTR pszSearch; + CComPtr & pFilter; +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] pszSrch Nom du filtre recherché. + * \param[out] pFltr Pointeur ATL destiné recevoir l'interface du filtre trouvé, s'il existe. + */ + CSearchByCategory_Get(CLSID clsid, LPCTSTR pszSrch, CComPtr & pFltr) : + CSearchByCategory(clsid), + pszSearch(pszSrch), + pFilter(pFltr) + { + myprintf(TEXT("CSearchByCategory_Get: clsid=") GUIDFMT TEXT(", nom=%s\n"), + GUIDPARM(clsid), pszSrch); + + pFltr.Release(); // précaution + } + + /** + * Implémentation de méthode virtuelle appelée pour chaque filtre trouvé. + * \param[in] pszName nom du filtre + * \param[in] pCurFltr interface vers ce filtre + * \retval true tant que le filtre n'a pas été trouvé + * \retval false quand le filtre a été trouvé, afin d'arrêter la recherche + */ + virtual HRESULT ApplyOne(CComPtr & pCurFltr, LPCTSTR pszName) + { + if (_tcscmp(pszName, pszSearch)==0) { + pFilter = pCurFltr; + return S_FALSE; + } + return S_OK; + } +}; Modifié: trunk/settings.cpp =================================================================== --- trunk/settings.cpp 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/settings.cpp 2008-11-28 11:06:47 UTC (rev 145) @@ -62,13 +62,13 @@ static LRESULT remplit_combo_tuner(HWND hItm, GUID guid, LPCWSTR nom) { - remplit_tuners(guid, hItm); + CSearchByCategory_FillCombo(guid, hItm).Do(); return SendMessage(hItm, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)nom); } static LRESULT remplit_combo_filtre(HWND hItm, GUID type, GUID subtype, LPCWSTR nom) { - search_filters(type, subtype, hItm); + CSearchByType_FillCombo(type, subtype, exact_match, hItm).Do(); return SendMessage(hItm, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)nom); } Supprimé: trunk/tools/ConditionalHeaderGenerator/ConditionalHeader.h =================================================================== --- trunk/tools/ConditionalHeaderGenerator/ConditionalHeader.h 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/tools/ConditionalHeaderGenerator/ConditionalHeader.h 2008-11-28 11:06:47 UTC (rev 145) @@ -1 +0,0 @@ -#include "b.h" \ Pas de fin de ligne à la fin du fichier Modifié: trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.cpp =================================================================== --- trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.cpp 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.cpp 2008-11-28 11:06:47 UTC (rev 145) @@ -1,7 +1,11 @@ // ConditionalHeaderGenerator.cpp : Defines the entry point for the console application. // -#include "stdafx.h" +#include +#include +#include +#include +#include BOOL ShowErr(void) { Modifié: trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.vcproj =================================================================== --- trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.vcproj 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.vcproj 2008-11-28 11:06:47 UTC (rev 145) @@ -186,10 +186,6 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > - - -#include -#include -#include -#include - -#pragma hdrstop Modifié: trunk/version.cmd =================================================================== --- trunk/version.cmd 2008-11-20 22:23:18 UTC (rev 144) +++ trunk/version.cmd 2008-11-28 11:06:47 UTC (rev 145) @@ -1,5 +1,11 @@ @echo off +rem Création de l'en-tête de compilation visant à différencier +rem Visual Studio 2005 et Visual C++ Express 2005: +if exist vstudio_edition.h goto vs_ed_exist +tools\ConditionalHeaderGenerator 3 > vstudio_edition.h +:vs_ed_exist + rem Cherche si on est dans un repository if not exist .svn\nul goto exporte From pouchintv-dev at baysse.fr Fri Nov 28 21:51:01 2008 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: Fri, 28 Nov 2008 21:51:01 +0100 (CET) Subject: [Pouchintv-dev] [PouchinTVMod] lolo_32 | r146 - in trunk: . LCD_Logitech LCD_Logitech/Win32 LCD_Logitech/x64 tools tools/ConditionalHeaderGenerator Message-ID: <20081128205101.829645F327@mail.baysse.fr> Author: lolo_32 Date: 2008-11-28 21:51:01 +0100 (ven, 28 nov 2008) New Revision: 146 Removed: trunk/tools/ConditionalHeaderGenerator.exe Modified: trunk/ trunk/Doxyfile trunk/LCD.cpp trunk/LCD.h trunk/LCD_Logitech/Win32/lgLcd.lib trunk/LCD_Logitech/lglcd.h trunk/LCD_Logitech/x64/lgLcd.lib trunk/Pouchin TV.sln trunk/Pouchin TV.vcproj trunk/base.cpp trunk/base.h trunk/ini.cpp trunk/ini.h trunk/internet.cpp trunk/internet.h trunk/main.cpp trunk/parse.cpp trunk/record.cpp trunk/record.h trunk/recprog.cpp trunk/res.rc trunk/resource.h trunk/settings.cpp trunk/settings.h trunk/tools/ trunk/tools/ConditionalHeaderGenerator/ trunk/tools/ConditionalHeaderGenerator/ConditionalHeaderGenerator.vcproj trunk/utils.cpp trunk/utils.h trunk/version.cmd trunk/xml.h Log: base.cpp, base.h, ini.cpp, ini.h, LCD.cpp, LCD.h, settings.cpp, settings.h, utils.cpp, utils.h, xml.h * ajout de commentaires exaustifs pour générer la documentation via Doxygen base.cpp, base.h: * ajout d'une fonction enregistrant les messages d'erreurs affichés dans les fenêtres de dialogue dans les fichiers de log via myprintf Doxyfile: * les macros ne sont plus étendues (ne convertis pas tous les "#define xxxx yy" en "yy" dans le code) ini.cpp, ini.h, res.rc: * ajout d'une option permettant de choisir le motif pour le nom des fichiers d'enregistrement internet.cpp, internet.h: * quelque optimisation * ajout de constantes pour les erreurs HTTP LCD.cpp, LCD.h: * ajout d'une fonction générique pour traiter les émissions main.cpp: * refonte de la gestion des paramètres de la ligne de commande settings.cpp: * rectification d'une erreur introduite par moi sur les valeurs conseillées des offsets en fonction des constructeurs version.cmd: * affiche diverses informations lors de l'exécution du fichier de commande Divers: * ajout du fichier "vstudio_edition.h" à la liste des fichiers ignorés * mise à jour de la librairie pour utiliser le LCD Logitech ConditionalHeader: * ajout du projet "Conditional Header" à la liste des projets, et ajout de celui-ci dans les prerequis * suppression de la version compilée de l'utilitaire Property changes on: trunk ___________________________________________________________________ Nom : svn:ignore - Debug Release Vista Debug Vista Release x64 chaines.xml config.ini pouchin.log Pouchin TV.suo Pouchin TV.ncb Pouchin TV.vcproj.* programmes.xml .*.swp version.txt res.aps PouchinTVMod*.exe + Debug Release Vista Debug Vista Release x64 chaines.xml config.ini pouchin.log Pouchin TV.suo Pouchin TV.ncb Pouchin TV.vcproj.* programmes.xml .*.swp version.txt res.aps PouchinTVMod*.exe vstudio_edition.h Modifié: trunk/Doxyfile =================================================================== --- trunk/Doxyfile 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/Doxyfile 2008-11-28 20:51:01 UTC (rev 146) @@ -1025,7 +1025,7 @@ # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. -MACRO_EXPANSION = YES +MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the Modifié: trunk/LCD.cpp =================================================================== --- trunk/LCD.cpp 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/LCD.cpp 2008-11-28 20:51:01 UTC (rev 146) @@ -44,15 +44,18 @@ this->m_initialise = InitialiseLcd(); if (!this->m_initialise) { + // Déconnecte du LCD car erreur, mais initialisation partielle + if (this->m_connectContext.connection) + lgLcdDisconnect(this->m_connectContext.connection); + + // Désinitialise le LCD (celui-ci ne sera plus utilisé) lgLcdDeInit(); return; } + // Efface toutes les variables privées ZeroMemory(this->m_chaine, sizeof(this->m_chaine)); - ZeroMemory(this->m_heure_actuel, sizeof(this->m_heure_actuel)); - ZeroMemory(this->m_prog_actuel, sizeof(this->m_prog_actuel)); - ZeroMemory(this->m_heure_suivant, sizeof(this->m_heure_suivant)); - ZeroMemory(this->m_prog_suivant, sizeof(this->m_prog_suivant)); + ZeroMemory(this->programmes, sizeof(this->programmes)); // Définit la police par défaut à utiliser ainsi que ses attributs // Taille de la police @@ -100,14 +103,19 @@ this->m_police_heure = NULL; } +/** + * Initialise le Lcd pour utilisation + * + * \retval true en cas de succès + * \retval false en cas d'erreur + **/ bool CLcd::InitialiseLcd() { DWORD ret = 0; ret = lgLcdInit(); - if (ret != ERROR_SUCCESS) { + if (ret != ERROR_SUCCESS) // Erreur d'initialisation de la bibliothèque return false; - } // Initialisation de la bibliothèque OK ! @@ -115,7 +123,7 @@ // Nom de l'affichage dans le LCD this->m_connectContext.appFriendlyName = szAppName; // Est-ce que ça démarre automatiquement? - this->m_connectContext.isAutostartable = FALSE; + this->m_connectContext.isAutostartable = TRUE; // L'écran doit-il rester affiché une fois l'application finie this->m_connectContext.isPersistent = FALSE; // Pas de configuration à l'aide des boutons @@ -126,26 +134,20 @@ // On se connecte ret = lgLcdConnect(&this->m_connectContext); - if(ret != ERROR_SUCCESS) { + if(ret != ERROR_SUCCESS) // Pas de LCD installé - lgLcdDeInit(); return false; - } // Le LCD est installé. // Recherche d'un LCD en fonctionnement ret = lgLcdEnumerate(this->m_connectContext.connection, 0, &this->m_lcdDeviceDesc); - if (ret != ERROR_SUCCESS) { + if (ret != ERROR_SUCCESS) // Pas de LCD en fonctionnement - lgLcdDisconnect(this->m_connectContext.connection); - lgLcdDeInit(); return false; - } // LCD trouvé // Ouverture de celui-ci - ZeroMemory(&this->m_openContext, sizeof(this->m_openContext)); // Associe l'ouverture à la connexion this->m_openContext.connection = this->m_connectContext.connection; @@ -159,17 +161,20 @@ // On ouvre l'écran ret = lgLcdOpen(&this->m_openContext); - if (ret != ERROR_SUCCESS) { - lgLcdDisconnect(this->m_connectContext.connection); - lgLcdDeInit(); + if (ret != ERROR_SUCCESS) return false; - } // Tout est OK // Maintenant, le LCD est initialisé return true; } +/** + * Réaffiche l'écran + * + * \retval ERROR_SUCCESS en cas de succès + * \return toute autre erreur en cas d'échec + **/ DWORD CLcd::ActualiseLcd() { if (! this->m_initialise) return ERROR_NOT_CAPABLE; @@ -205,12 +210,16 @@ } // actualise l'affichage - ret = lgLcdUpdateBitmap(this->m_openContext.device, &(bitmap.hdr), LGLCD_ASYNC_UPDATE(LGLCD_PRIORITY_NORMAL)); + ret = lgLcdUpdateBitmap(this->m_openContext.device, &(bitmap.hdr), LGLCD_ASYNC_UPDATE(LGLCD_PRIORITY_ALERT)); ZeroMemory(&winbitmap, sizeof(winbitmap)); SetBitmapBits(this->m_bitmap, 860, &winbitmap); return ERROR_SUCCESS; } + +/** + * Met à jour les textes : Chaîne, Volume, programmes + **/ void CLcd::UpdateTexte() { TEXTMETRIC tm; @@ -220,7 +229,7 @@ // Pour avoir la hauteur de la police GetTextMetrics(this->m_hdc, &tm); - // Chaine en haut à gauche + // chaîne en haut à gauche SetTextAlign(this->m_hdc, TA_LEFT); TextOutA(this->m_hdc, 10, 1, this->m_chaine, (int)strlen(this->m_chaine)); @@ -238,35 +247,76 @@ // Programme actuel gauche SelectObject(this->m_hdc, this->m_police_heure); - TextOutA(this->m_hdc, 1, tm.tmHeight + 2, this->m_heure_actuel, (int)strlen(this->m_heure_actuel)); + TextOutA(this->m_hdc, 1, tm.tmHeight + 2, this->programmes[0].heure, (int)strlen(this->programmes[0].heure)); SelectObject(this->m_hdc, this->m_police); - TextOutA(this->m_hdc, tm.tmAveCharWidth * 8, tm.tmHeight + 1, this->m_prog_actuel, (int)strlen(this->m_prog_actuel)); + TextOutA(this->m_hdc, tm.tmAveCharWidth * 8, tm.tmHeight + 1, this->programmes[0].prog, (int)strlen(this->programmes[0].prog)); // Programme suivant gauche SelectObject(this->m_hdc, this->m_police_heure); - TextOutA(this->m_hdc, 1, (tm.tmHeight + 1)*2+1, this->m_heure_suivant, (int)strlen(this->m_heure_suivant)); + TextOutA(this->m_hdc, 1, (tm.tmHeight + 1)*2+1, this->programmes[1].heure, (int)strlen(this->programmes[1].heure)); SelectObject(this->m_hdc, this->m_police); - TextOutA(this->m_hdc, tm.tmAveCharWidth * 8, (tm.tmHeight + 1)*2, this->m_prog_suivant, (int)strlen(this->m_prog_suivant)); + TextOutA(this->m_hdc, tm.tmAveCharWidth * 8, (tm.tmHeight + 1)*2, this->programmes[1].prog, (int)strlen(this->programmes[1].prog)); } +/** + * Définit le nom de la chaîne actuelle + * + * \param[in] nomChaine Nom de la chaîne + **/ void CLcd::SetChaine(const char *nomChaine){ + if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici + strncpy_s(this->m_chaine, _countof(this->m_chaine), nomChaine, _countof(this->m_chaine)-1); } +/** + * Définit le nom et heure du programme passé en paramètre + * + * \param[in] heure la date/heure du déut du programme + * \param[in] programme le nom du programme + * \param[in] num position du programme + **/ +void CLcd::SetProgramme(const SYSTEMTIME &heure, const char *programme, const int num){ + if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici + + TimeToStr(heure, this->programmes[num].heure, _countof(this->programmes[num].heure)); + strncpy_s(this->programmes[num].prog, _countof(this->programmes[num].prog), programme, _countof(this->programmes[num].prog)); +} + + +/** + * Définit le nom et heure du programme actuel + * + * \param[in] heure la date/heure du déut du programme + * \param[in] programme le nom du programme + **/ void CLcd::SetProgrammeActuel(const SYSTEMTIME &heure, const char *programme){ - TimeToStr(heure, this->m_heure_actuel, _countof(this->m_heure_actuel)); - strncpy_s(this->m_prog_actuel, _countof(this->m_prog_actuel), programme, _countof(this->m_prog_actuel)); + if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici + + SetProgramme(heure, programme, 0); } +/** + * Définit le nom et heure du programme suivant + * + * \param[in] heure la date/heure du déut du programme + * \param[in] programme le nom du programme + **/ void CLcd::SetProgrammeSuivant(const SYSTEMTIME &heure, const char *programme){ - TimeToStr(heure, this->m_heure_suivant, _countof(this->m_heure_suivant)); - strncpy_s(this->m_prog_suivant, _countof(this->m_prog_suivant), programme, _countof(this->m_prog_suivant)-1); + if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici + + SetProgramme(heure, programme, 1); } +/** + * Fait passer le programme suivant en programme actuel + **/ void CLcd::SetSuivant(){ - strcpy_s(this->m_heure_actuel, _countof(this->m_heure_actuel), this->m_heure_suivant); - ZeroMemory(this->m_heure_suivant, sizeof(this->m_heure_suivant)); + if (!this->m_initialise) return; // Pas initialisé, donc, pas besoin de perdre du temps ici - strcpy_s(this->m_prog_actuel, _countof(this->m_prog_actuel), this->m_prog_suivant); - ZeroMemory(this->m_prog_suivant, sizeof(this->m_prog_suivant)); + strcpy_s(this->programmes[0].heure, _countof(this->programmes[0].heure), this->programmes[1].heure); + ZeroMemory(this->programmes[1].heure, sizeof(this->programmes[1].heure)); + + strcpy_s(this->programmes[0].prog, _countof(this->programmes[0].prog), this->programmes[1].prog); + ZeroMemory(this->programmes[1].prog, sizeof(this->programmes[1].prog)); } Modifié: trunk/LCD.h =================================================================== --- trunk/LCD.h 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/LCD.h 2008-11-28 20:51:01 UTC (rev 146) @@ -29,44 +29,67 @@ #include "LCD_Logitech/lglcd.h" +/** + * Classe permettant de gérer, et modifier l'affichage sur les écrans LCD + **/ class CLcd { protected: - // 0 => pas de LCD trouvé ou erreur activation - // 1 => LCD trouvé et activé + /// 0 => pas de LCD trouvé ou erreur activation + /// 1 => LCD trouvé et activé bool m_initialise; - // Contexte de la connexion du LCD - // C'est à partir de lui que se fait la config de l'affichage + /// Contexte de la connexion du LCD + /// C'est à partir de lui que se fait la config de l'affichage lgLcdConnectContext m_connectContext; - // Contexte de l'ouverture du LCD + /// Contexte de l'ouverture du LCD lgLcdOpenContext m_openContext; - // Descriptifs de l'écran + /// Descriptifs de l'écran lgLcdDeviceDesc m_lcdDeviceDesc; - // Handle pour dessiner le bitmap + /// Handle pour dessiner le bitmap HDC m_hdc; - // Police à utiliser + /// Police à utiliser HFONT m_police, m_police_heure; - // Image à afficher + /// Image à afficher HBITMAP m_bitmap; - // Nom de la chaine actuelle + /// Nom de la chaîne actuelle char m_chaine[256]; - // Heures des début - char m_heure_actuel[32], m_heure_suivant[32]; - // Nom des programmes - char m_prog_actuel[256], m_prog_suivant[256]; - // Volume + /// Définit les programmes (actuel et suivant) + struct { + /// heure de début de diffusion + char heure[32]; + /// nom du programme + char prog[256]; + } programmes[2]; + + /// Volume long m_volume; - // En sourdine + /// En sourdine bool m_mute; - // Initialise le LCD + /** + * Initialise le Lcd pour utilisation + * + * \retval true en cas de succès + * \retval false en cas d'erreur + **/ bool InitialiseLcd(); - // Affiche la chaine + programmes + /** + * Met à jour les textes : Chaîne, Volume, programmes + **/ void UpdateTexte(); + /** + * Définit le nom et heure du programme passé en paramètre + * + * \param[in] heure la date/heure du déut du programme + * \param[in] programme le nom du programme + * \param[in] num position du programme + **/ + void SetProgramme(const SYSTEMTIME &heure, const char *programme, const int num); + public: enum { DEFAULT_POINTSIZE = 8, @@ -75,24 +98,45 @@ CLcd(); ~CLcd(); - // Re-affiche l'écran + /** + * Réaffiche l'écran + * + * \retval ERROR_SUCCESS en cas de succès + * \return toute autre erreur en cas d'échec + **/ DWORD ActualiseLcd(); - // Définit la chaine + /** + * Définit le nom de la chaîne actuelle + * + * \param[in] nomChaine Nom de la chaîne + **/ void SetChaine(const char *nomChaine); - // Définit le programme actuel + /** + * Définit le nom et heure du programme actuel + * + * \param[in] heure la date/heure du déut du programme + * \param[in] programme le nom du programme + **/ void SetProgrammeActuel(const SYSTEMTIME &heure, const char *programme); - // Définit le programme suivant + /** + * Définit le nom et heure du programme suivant + * + * \param[in] heure la date/heure du déut du programme + * \param[in] programme le nom du programme + **/ void SetProgrammeSuivant(const SYSTEMTIME &heure, const char *programme); - // Fait passer le programme suivant en programme actuel + /** + * Fait passer le programme suivant en programme actuel + **/ void SetSuivant(); - // Définit le volume à afficher + /// Définit le volume à afficher void SetVolume(const long &volume) { this->m_volume = (volume+8000)/80; ActualiseLcd();} - // On est en sourdine + /// On est en sourdine void Mute(const bool &muted) { this->m_mute = muted; ActualiseLcd(); } - // Indique si le LCD est initialisé + /// Indique si le LCD est initialisé bool IsInitialise() { return this->m_initialise; } }; Modifié: trunk/LCD_Logitech/Win32/lgLcd.lib =================================================================== (les fichiers binaires diffèrent) Modifié: trunk/LCD_Logitech/lglcd.h =================================================================== --- trunk/LCD_Logitech/lglcd.h 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/LCD_Logitech/lglcd.h 2008-11-28 20:51:01 UTC (rev 146) @@ -123,6 +123,7 @@ #define LGLCD_DEVICE_FAMILY_SPEAKERS_Z10 (0x00000002) #define LGLCD_DEVICE_FAMILY_JACKBOX (0x00000004) #define LGLCD_DEVICE_FAMILY_LCDEMULATOR_G15 (0x00000008) +#define LGLCD_DEVICE_FAMILY_RAINBOW (0x00000010) #define LGLCD_DEVICE_FAMILY_OTHER (0x80000000) // Capabilities of applets connecting to LCD Manager. Modifié: trunk/LCD_Logitech/x64/lgLcd.lib =================================================================== (les fichiers binaires diffèrent) Modifié: trunk/Pouchin TV.sln =================================================================== --- trunk/Pouchin TV.sln 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/Pouchin TV.sln 2008-11-28 20:51:01 UTC (rev 146) @@ -2,11 +2,14 @@ # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pouchin TV", "Pouchin TV.vcproj", "{E40974CC-65ED-4E0D-A2E2-3885C2C8A25B}" ProjectSection(ProjectDependencies) = postProject + {04EF8AA7-57C0-4015-8E90-FA565934F78A} = {04EF8AA7-57C0-4015-8E90-FA565934F78A} {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA} = {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BaseClasses", "BaseClasses\baseclasses.vcproj", "{E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConditionalHeaderGenerator", "tools\ConditionalHeaderGenerator\ConditionalHeaderGenerator.vcproj", "{04EF8AA7-57C0-4015-8E90-FA565934F78A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -51,6 +54,18 @@ {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Release|Win32.Build.0 = Release|Win32 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Release|x64.ActiveCfg = Release|x64 {E8A3F6FA-AE1C-4C8E-A0B6-9C8480324EAA}.Vista Release|x64.Build.0 = Release|x64 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Debug|Win32.ActiveCfg = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Debug|Win32.Build.0 = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Debug|x64.ActiveCfg = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Release|Win32.ActiveCfg = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Release|Win32.Build.0 = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Release|x64.ActiveCfg = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Vista Debug|Win32.ActiveCfg = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Vista Debug|Win32.Build.0 = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Vista Debug|x64.ActiveCfg = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Vista Release|Win32.ActiveCfg = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Vista Release|Win32.Build.0 = Release|Win32 + {04EF8AA7-57C0-4015-8E90-FA565934F78A}.Vista Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modifié: trunk/Pouchin TV.vcproj =================================================================== --- trunk/Pouchin TV.vcproj 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/Pouchin TV.vcproj 2008-11-28 20:51:01 UTC (rev 146) @@ -147,6 +147,7 @@ /> @@ -847,6 +866,10 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + @@ -992,10 +1015,6 @@ RelativePath=".\resource.h" > - - + + Modifié: trunk/base.cpp =================================================================== --- trunk/base.cpp 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/base.cpp 2008-11-28 20:51:01 UTC (rev 146) @@ -29,15 +29,70 @@ #include "main.h" #include "ini.h" +/** + * \file + * Fonctions pour gérer les erreurs + */ + +/// Handle de la fenêtre principale de l'application HWND hMainWnd = NULL; +/// Chaîne de caractères contenant tous les messages d'erreurs concaténés static LPTSTR pszErrBuf = NULL; +/// Dernier code d'erreur traité (pour éviter la multiplication des messages identiques) static HRESULT lastRes = S_OK; +#if USE_CONSOLE +/** + * Enregistre le message d'erreur dans les logs (au cas où ils doivent être étudiés) + * en rajoutant l'heure d'intervention + * + * \param[in] str Message d'erreur à afficher dans le log + **/ +void myprintferror(LPWSTR str) { + wchar_t buffer[0x200] = {0}; + + SYSTEMTIME time; + GetLocalTime(&time); + + LPWSTR pszBuffer = str; + // Remplace les nouvelles lignes par " / ", ce qui évite d'avoir de nouvelles + // lignes inutiles (car même erreur) dans le log généré + while(wchar_t *lpcNl = wcschr(pszBuffer, L'\n')) { + wcsncat_s(buffer, _countof(buffer), pszBuffer, (int)(lpcNl - pszBuffer)); + wcscat_s(buffer, _countof(buffer), L" / "); + pszBuffer = lpcNl+1; + } + wcscat_s(buffer, _countof(buffer), pszBuffer); + pszBuffer = buffer; + while(wchar_t *lpcNl = wcschr(pszBuffer, L'\r')) { + wcsncat_s(buffer, _countof(buffer), pszBuffer, (int)(lpcNl - pszBuffer)); + pszBuffer = lpcNl+1; + } + wcscat_s(buffer, _countof(buffer), pszBuffer); + myprintf(L"Erreur# %d:%d:%d %s\n", time.wHour, time.wMinute, time.wSecond, buffer); +} +#else // #if USE_CONSOLE +/// Pas de console, donc, pas de log +#define myprintferror(str) +#endif + +/** + * 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 + **/ 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; va_list argptr; @@ -57,29 +112,43 @@ _tcscpy_s(pszNewErrBuf, nBufLen, pszErrBuf); _tcscat_s(pszNewErrBuf, nBufLen, pszEol); _tcscat_s(pszNewErrBuf, nBufLen, buffer); - delete pszErrBuf; + delete [] pszErrBuf; } else { pszNewErrBuf = new TCHAR[nBufLen]; _tcscpy_s(pszNewErrBuf, nBufLen, buffer); } pszErrBuf = pszNewErrBuf; + + // Logue le message d'erreur + myprintferror(pszNewErrBuf); } if (FAILED(hr) && hr!=lastRes) { - AMGetErrorText(hr, buffer, _countof(buffer)); + AMGetErrorTextW(hr, buffer, _countof(buffer)); erreur(TEXT("%s (code 0x%08x)"), S_OK, buffer, hr); lastRes = hr; } + return 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 +**/ void affiche_erreurs(LPCTSTR str, HRESULT hr) { + // Met le nouveau message d'erreur en file 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; + delete [] pszErrBuf; pszErrBuf = NULL; lastRes = S_OK; } Modifié: trunk/base.h =================================================================== --- trunk/base.h 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/base.h 2008-11-28 20:51:01 UTC (rev 146) @@ -27,13 +27,12 @@ #pragma once -// Utiliser VMR9 +/// Utiliser VMR9 ? #define USE_VMR9 0 #define _WIN32_DCOM -/* Pour éviter les problèmes de compatibilité entre qedit.h et vrm9.h */ - +/** Pour éviter les problèmes de compatibilité entre qedit.h et vrm9.h */ #ifndef __D3DRM_H__ #define __D3DRM_H__ #endif @@ -71,7 +70,6 @@ // En effet, les modèles de classes ATL ne sont pas disponibles dans l'environnement // Visual C++ 2005 Express, à moins d'avoir installé ces classes depuis une autre // source. Voir commentaires dans le fichier atlbase_ptvm.h. - #include "vstudio_edition.h" #ifndef COMPILER_EDITION_VCEXPRESS @@ -83,31 +81,39 @@ #include "resource.h" -// Décommenter si on veut afficher la console de debugging : +/** + * \def USE_CONSOLE + * Décommenter si on veut afficher la console de debugging + * + * On peut aussi mettre USE_CONSOLE=-1, afin d'envoyer les messages + * d'erreur vers la fonction OutputDebugString, pour ensuite les + * récupérer avec un debugger ou bien un logiciel tel que DebugView : + * http://www.microsoft.com/TechNet/Sysinternals/Utilities/DebugView.mspx + **/ //#define USE_CONSOLE 1 -// -// On peut aussi mettre USE_CONSOLE=-1, afin d'envoyer les messages -// d'erreur vers la fonction OutputDebugString, pour ensuite les -// récupérer avec un debugger ou bien un logiciel tel que DebugView : -// http://www.microsoft.com/TechNet/Sysinternals/Utilities/DebugView.mspx #include "console.h" #ifdef _DEBUG -# define EXPORT_GRAPH 1 -# define LOG_DSHOW 1 // Enregistrer DShow + /// on exporte le graphe DShow + #define EXPORT_GRAPH 1 + /// Enregistrer DShow + #define LOG_DSHOW 1 #else -# define EXPORT_GRAPH 0 -# define LOG_DSHOW 0 + /// pas d'export du graphique DShow + #define EXPORT_GRAPH 0 + /// on ne logue pas les évènements DShow + #define LOG_DSHOW 0 #endif -// Activer le LCD Logitech -//#define USE_LOGITECH_LCD +/// \def USE_LOGITECH_LCD +/// Activer le LCD Logitech +#define USE_LOGITECH_LCD -// Nombre max de chaînes +/// Nombre max de chaînes #define NB_MAX_CHAINES 500 -// Nombre max d'enregistrements simultanés sur un même multiplex +/// Nombre max d'enregistrements simultanés sur un même multiplex #define NB_MAX_ENREG 3 /////////////////////////////////////////////////////////////////// @@ -119,13 +125,13 @@ // Macros d'assistance à l'insertion conditionnelle de courtes séquences de code en mode debugging : // (utile en particulier s'il s'agit de paramètres supplémentaires de fonctions) #if USE_CONSOLE -#define IF_DEBUG(code) code -#define IF_DEBUG_CA(code) code , // virgule après ("comma after") -#define IF_DEBUG_CB(code) , code // virgule avant ("comma before") +#define IF_DEBUG(code) code ///< code conditionnel exécuté seulement en compilation debug +#define IF_DEBUG_CA(code) code , ///< code conditionnel exécuté seulement en compilation debug, avec une virgule après ("comma after") +#define IF_DEBUG_CB(code) , code ///< code conditionnel exécuté seulement en compilation debug, avec une virgule avant ("comma before") #else -#define IF_DEBUG(code) -#define IF_DEBUG_CA(arg) -#define IF_DEBUG_CB(arg) +#define IF_DEBUG(code) ///< désactive le code debug +#define IF_DEBUG_CA(arg) ///< désactive le code debug +#define IF_DEBUG_CB(arg) ///< désactive le code debug #endif #if defined _M_IX86 @@ -139,6 +145,7 @@ #endif #if USE_VMR9 + // Fonctions VMR9 à utiliser #define MyV(a) a ## 9 @@ -150,6 +157,7 @@ #define MyMIXINGPREFS (MixerPref9_NoDecimation | MixerPref9_BiLinearFiltering | MixerPref9_RenderTargetYUV) #else // #if USE_VMR9 + // Fonctions VMR7 à utiliser #define MyV(a) a @@ -166,31 +174,52 @@ #define _cmd_ MAKEWPARAM #define _ncode_(lParam) LPNMHDR(lParam)->code - +/// Couleur de fond de la fenêtre, remplacée par l'image const COLORREF colorKey = RGB(0,0,1); +/// GUID pour le codec h264 const GUID guid_H264 = { 0x31435641, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71} }; +/// Structure décrivant une fréquence struct Frequence { - WORD canal_no; - long mhz; + WORD canal_no; ///< numéro du canal (de 1 à 60) + long mhz; ///< fréquence (canal convertis en mhz) }; +/// Permet de décrire les fichiers inclus dans les resources de PTVM struct RcdataResource { - int taille; - LPBYTE contenu; + int taille; ///< taille de la ressource concernée + LPBYTE contenu; ///< contenu de la ressource }; +/// Définit le type d'affichage de la fenêtre de PTVM enum EtatsFenetre { - etf_normal, // normal avec bordures - etf_noborders, // normal sans bordures - etf_maximized, // maximisé (avec bordures) - etf_fullscreen, // plein écran (sans bordures) - etf_minimized // minimisée (en icône ou pas) + etf_normal, ///< normal avec bordures + etf_noborders, ///< normal sans bordures + etf_maximized, ///< maximisé (avec bordures) + etf_fullscreen, ///< plein écran (sans bordures) + etf_minimized ///< minimisée (en icône ou pas) }; +/** + * 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 + **/ 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 +**/ void affiche_erreurs(LPCTSTR str, HRESULT hr=S_OK); Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/ini.cpp 2008-11-28 20:51:01 UTC (rev 146) @@ -37,23 +37,40 @@ #include #include // pour 'sort' -// Nom de base du fichier définissant les villes et les canaux +/// Nom de base du fichier définissant les villes et les canaux wchar_t scan_ini[]=L"canaux.ini"; -static wchar_t general[]=L"Général"; - +/// Position de la fenêtre (enregistré) de PTVM WindowPos winPos; -// Priorité du processus courant selon la configuration +/// Priorité du processus courant selon la configuration DWORD configPriority = IDM_ABOVE_NORMAL_PRIORITY; -// État de la fenêtre principale selon la configuration +/// État de la fenêtre principale selon la configuration EtatsFenetre configState = etf_normal; +/** + * Motif pour le nom des fichiers pour les enregistrements, ainsi que la valeur par défaut +
+ *    %c = chaîne
+ *    %n = numéro de chaîne
+ *    %e = nom de l'enregistrement
+ *    %a = année
+ *    %m = mois
+ *    %j = jour
+ *    %h = heure
+ *    %M = minute
+ *    %s = secondes
+ **/ +wchar_t nom_enregistrement[MAX_PATH]; +/// Motif par défaut pour nommer les enregistrements +static const wchar_t nom_enregistrement_default[] = L"%n-%e %a-%m-%j %h-%M-%s"; + +/// Convertit directement un numéro de canal en fréquence, en rajoutant l'offset de correction de fréquence #define freq_canal(x) (x * 8000 + freq_offset) -static wchar_t config_file[] = L"config.ini"; -static wchar_t ini_config[] = L"Config"; +static wchar_t config_file[] = L"config.ini"; ///< Nom du fichier de configuration +static wchar_t ini_config[] = L"Config"; ///< Nom de la section contenant la configuration #if _DEBUG static wchar_t ini_filtre_MPEG2[] = L"Filtre MPEG2 (debug)"; static wchar_t ini_filtre_audio[] = L"Filtre audio (debug)"; @@ -82,6 +99,7 @@ static wchar_t ini_etirer_video[] = L"Étirer la vidéo"; static wchar_t ini_zoom_ratio[] = L"Facteur de zoom"; static wchar_t ini_volume[] = L"Volume"; +static wchar_t ini_nom_enregistrement[] = L"Nom du fichier d'enregistrement"; static wchar_t ini_position_fenetre[]=L"Position fenêtre"; @@ -92,6 +110,12 @@ static wchar_t ini_use_vmr_deinterlace[]=L"Utilise le désentrelacement du VMR"; static wchar_t ini_etat_fenetre[] =L"État fenêtre"; +/** + * Constructeur permettant de remplacer les caractères invalides (\"*:/<>?|) pour des noms de fichiers par un caractère valide + * + * \param[in] src nom du fichier à convertir + * \param[in] remplacement caractère de remplacement en cas de caractère invalide + **/ NomProtege::NomProtege(LPCSTR src, char remplacement) { LPSTR pcar; @@ -105,32 +129,134 @@ nom[0] = 0; } -// Extraction d'une copie Unicode : +/** + * Extraction d'une copie Unicode + * + * \param[out] lpWideCharStr chaîne unicode resultante + * \param[in] cchWideChar nombre de caractères pouvant contenir lpWideCharStr + * \return le nombre de caractères convertis, ou 0 en cas d'erreur + **/ int NomProtege::ToWide(LPWSTR lpWideCharStr, int cchWideChar) const { return MultiByteToWideChar(CP_ACP, 0, nom, -1, lpWideCharStr, cchWideChar); } -NomFichierAvecDate::NomFichierAvecDate(LPCWSTR dir, LPCSTR prefixe1, LPCSTR prefixe2, LPCSTR extension) +/** + * Constructeur permettant de générer le nom du fichier d'enregistrement + * + * \param[in] dir dossier pour l'enregistrement du fichier + * \param[in] prefixe1 nom de l'enregistrement (seulement en cas de programmation d'enregistrement) + * \param[in] prefixe2 nom de la chaîne enregistrée + * \param[in] extension extention du fichier (permet de définir le type du fichier (BMP, MPG, TS, ...) + **/ +NomFichierAvecDate::NomFichierAvecDate(LPCWSTR dir, LPCSTR prefixe1, LPCSTR prefixe2, LPCWSTR extension) { + // Remplace les caractères invalides par des espaces NomProtege prefix_prot1(prefixe1, ' '); NomProtege prefix_prot2(prefixe2, ' '); + // Date/heure de l'enregistrement SYSTEMTIME localtime; GetLocalTime(&localtime); - swprintf_s( - nom, _countof(nom), - L"%s\\%S%S%S %04i-%02i-%02i %02i-%02i-%02i.%S", - dir, prefix_prot1.nom, - prefix_prot1.nom[0]!=0 && prefix_prot2.nom[0]!=0 ? " - " : "", - prefix_prot2.nom, - localtime.wYear, localtime.wMonth, localtime.wDay, - localtime.wHour, localtime.wMinute, localtime.wSecond, - extension); + // Récupère le numéro de la chaîne (si possible): + int nr_chaine = -1; + for (size_t i=0; igetInt(xstn.name_wYear); @@ -247,6 +394,7 @@ **/ int lit_programmes(void) { + // Noms des noeud actuels static const XMLSystemTimeNames Xstn_std = { L"Annee", L"Mois", @@ -257,6 +405,7 @@ L"Seconde" }; + // Anciens nom de début d'enregistrement static const XMLSystemTimeNames Xstn_S = { L"S_Annee", L"S_Mois", @@ -267,6 +416,7 @@ L"S_Seconde" }; + // Anciens nom de fin d'enregistrement static const XMLSystemTimeNames Xstn_E = { L"E_Annee", L"E_Mois", @@ -277,9 +427,11 @@ L"E_Seconde" }; + // Efface les programmes actuels Programmes.clear(); CXMLWrapper xml; + // Nom complet du fichier décrivant les programmes (enregistrements) wchar_t fileName[MAX_PATH]; wcscpy_s(fileName, _countof(fileName), pouchindir_conf); wcscat_s(fileName, _countof(fileName), L"programmes.xml"); @@ -314,23 +466,29 @@ prog.sidChaine = indexToSID(trouve_chaine_par_no(prog.numeroChaine)); // Récupère les heures/dates de début d'enregistrement + // cherche aussi à récupérer avec les anciens noms des noeuds CXMLNode *enregistrements = NULL; pNode->getChildrenByName(L"Début", &enregistrements); if (enregistrements) { + // Nouveau style (dans un noeud distinct) xmlLoadSystemTime(enregistrements, prog.debut, Xstn_std); delete enregistrements; enregistrements = NULL; } else { + // Ancien style xmlLoadSystemTime(pNode, prog.debut, Xstn_S); } // Récupère les heures/dates de fin d'enregistrement + // cherche aussi à récupérer avec les anciens noms des noeuds pNode->getChildrenByName(L"Fin", &enregistrements); if (enregistrements) { + // Nouveau style (dans un noeud distinct) xmlLoadSystemTime(enregistrements, prog.fin, Xstn_std); delete enregistrements; enregistrements = NULL; } else { + // Ancien style xmlLoadSystemTime(pNode, prog.fin, Xstn_E); } @@ -365,6 +523,13 @@ return 0; } +/** + * Fonction permettant d'enregistrer dans un nouveau noeud XML la date passée + * + * \param[in] oxml objet CXMLOutput où enregistrer la date + * \param[in] section nom du noeud + * \param[in] stim date à enregistrer + **/ void xmlSaveSystemTime(CXMLOutput & oxml, LPCSTR section, const SYSTEMTIME & stim) { CXMLOpenChild oxmlc(oxml, section); @@ -447,10 +612,13 @@ /** * Chargement du fichier des chaînes "chaines.xml". - * Retourne 0 en cas de succès, 1 si erreur. + * + * \retval 0 en cas de succès + * \retval 1 si erreur **/ int lit_chaines() { + // Fichier XML CXMLWrapper xml; wchar_t fileName[MAX_PATH]; wcscpy_s(fileName, _countof(fileName), pouchindir_conf); @@ -462,9 +630,11 @@ return 1; } + // Récupère le noeud racine CXMLElement root = xml.getDocElement(); wchar_t var[16]; + // Tous les enfants (toutes les chaînes) std::vector children = root.getChildren(); for (size_t i=0; igetInt(L"PMT"); canal.pcr_pid = (WORD)pNode->getInt(L"PCR"); + // Détermine le type de flux vidéo if ((canal.video_pid = (UINT16)pNode->getInt(L"Video"))!=0) canal.video_type = vst_MPEG2; else if ((canal.video_pid = (UINT16)pNode->getInt(L"Video_mpeg4"))!=0) @@ -502,6 +673,7 @@ else canal.video_type = vst_Unknown; + // Récupère les pistes son canal.sons.nbr = (WORD)pNode->getInt(L"Nb_Son"); for (int i=0;igetStr(var, canal_son.lang, _countof(canal_son.lang)); } + // Récupère les autres information canal.autr.nbr = (WORD)pNode->getInt(L"Nb_Autre"); for (int i=0;igetStr(var, canal_autre.lang, _countof(canal_autre.lang)); } + // Mémorise le canal généré Canaux.push_back(canal); delete pNode; @@ -535,21 +709,29 @@ } +/** + * Mémorise la liste des chaînes + **/ void sauve_chaines(void) { + // Nombre de chaines int nbChaines = (int)Canaux.size(); + // Nom complet du fichier contenant les chaînes wchar_t fileName[MAX_PATH]; wcscpy_s(fileName, _countof(fileName), pouchindir_conf); wcscat_s(fileName, _countof(fileName), L"chaines.xml"); + // Fichier XML pour mémoriser les chaînes CXMLOutput oxml(fileName); if (!oxml.opened()) return; + // Noeud racine du fichier XML CXMLOpenChild oxmlc1(oxml, "Chaines"); for (int i=0; i terminateur }; +/** + * Tableau associatif décrivant les prioritées de PTVM pour sauvegarde + **/ AssocElement aPrioTable[] = { {L"Basse", IDLE_PRIORITY_CLASS}, @@ -619,6 +810,9 @@ {NULL, 0} // -> terminateur }; +/** + * Tableau associatif décrivant les différents affichages de la fenêtre pour sauvegarde + **/ AssocElement aWStateTable[] = { {L"Normale", etf_normal}, @@ -629,13 +823,34 @@ {NULL, 0} // -> terminateur }; +/** + * Chemin complet vers le fichier de configuration.\n + * Normalement, il se trouve dans "%appdata%\Pouchin TV Mod", + * mais il peut se trouver dans le répertoire courant de PTVM si le fichier dans %appdata% n'existe pas + **/ static wchar_t confPathName[MAX_PATH]; +/** + * Sauve la chaîne de caractères passée en paramètre + * + * \param[in] lpKeyName nom de la clé devant être utilisée + * \param[in] lpString chaîne de caractères à enregistrer + * \retval "une valeur non nule" en cas de succès + * \retval 0 en cas d'erreur + **/ BOOL save_config_str(LPCWSTR lpKeyName, LPCWSTR lpString) { return WritePrivateProfileString(ini_config, lpKeyName, lpString, confPathName); } +/** + * Écrit une valeur numérique + * + * \param[in] lpKeyName nom de la clé devant être utilisée + * \param[in] value valeur numérique à enregistrer + * \retval "une valeur non nule" en cas de succès + * \retval 0 en cas d'erreur + **/ BOOL save_config_int(LPCWSTR lpKeyName, LONG value) { wchar_t valeur[64]; @@ -644,18 +859,41 @@ return save_config_str(lpKeyName, valeur); } -// Écriture de la chaîne de caractères associée à une valeur fournie : +/** + * Écriture de la chaîne de caractères associée à une valeur fournie + * + * \param[in] lpKeyName nom de la clé devant être utilisée + * \param[in] assocTable AssocElement contenant le tableau à traduire + * \param[in] value valeur numérique devant être converti en chaine de caractères + * \retval "une valeur non nule" en cas de succès + * \retval 0 en cas d'erreur + **/ BOOL save_config_assoc(LPCWSTR lpKeyName, const AssocElement * assocTable, DWORD value) { return save_config_str(lpKeyName, dword2str(assocTable, value)); } +/** + * Sauvegarde un booléen + * + * \param[in] lpKeyName nom de la clé devant être utilisée + * \param[in] value valeur à enregistrer + * \retval "une valeur non nule" en cas de succès + * \retval 0 en cas d'erreur + **/ BOOL save_config_bool(LPCWSTR lpKeyName, bool value) { return save_config_assoc(lpKeyName, aBoolTable, value); } -// Sauvegarde d'une position normale de fenêtre : +/** + * Sauvegarde d'une position normale de fenêtre + * + * \param[in] lpKeyName nom de la clé devant être utilisée pour enregistrer la position/taille de la fenêtre + * \param[in] hWnd handle de la fenêtre sui doit être sauvegardée + * \retval 0 en cas d'échec + * \retval "toute autre valeur" en cas de succès + **/ BOOL save_config_winpos(LPCWSTR lpKeyName, HWND hWnd) { WINDOWPLACEMENT wpl; @@ -670,6 +908,9 @@ return save_config_str(lpKeyName, position); } +/** + * Sauvegarde tous les paramètres de configuration + **/ void save_config(void) { save_config_str(ini_tuner, nom_tuner); @@ -702,16 +943,40 @@ save_config_int(ini_volume, (volumeCourant + 10000) / 100); } +/** + * Cherche une chaîne de caractères dans le fichier de configuration + * + * \param[in] lpKeyName nom de l'option rechercher + * \param[out] lpValue valeur recherchée + * \param[in] bufSize nombre de caractères dans la chaîne de retours + * \param[in] lpDefault valeur par défaut, si on n'a rien trouvé + * \return Nombre de caractères copiés, sans tenir compte du caractère '\\0' + **/ DWORD load_config_str(LPCWSTR lpKeyName, LPWSTR lpValue, DWORD bufSize, LPCWSTR lpDefault=L"") { return GetPrivateProfileString(ini_config, lpKeyName, lpDefault, lpValue, bufSize, confPathName); } +/** + * Cherche une valeur numérique dans le fichier de configuration + * + * \param[in] lpKeyName nom de l'option rechercher + * \param[in] nDefault valeur par défaut, si on n'a rien trouvé + * \return valeur recherchée (trouvée, ou par défaut) + **/ UINT load_config_int(LPCWSTR lpKeyName, INT nDefault) { return GetPrivateProfileInt(ini_config, lpKeyName, nDefault, confPathName); } +/** + * Cherche une valeur numérique, en convertissant la valeur textuelle contenue dans le fichier de configuration + * + * \param[in] lpKeyName nom de l'option rechercher + * \param[in] assocTable tableau associatif contenant les faleurs à rechercher + * \param[in] bydefault valeur par défaut, si on n'a rien trouvé + * \return valeur recherchée (trouvée, ou par défaut) + **/ DWORD load_config_assoc(LPCWSTR lpKeyName, const AssocElement * assocTable, DWORD bydefault) { wchar_t str[32]; @@ -720,11 +985,26 @@ return str2dword(assocTable, str, bydefault); } +/** + * Charge une valeur binaire dans le fichier de configuration, en convertissant les valeurs textuelles + * + * \param[in] lpKeyName nom de l'option rechercher + * \param[in] bydefault valeur par défaut, si on n'a rien trouvé + * \return valeur recherchée (trouvée, ou par défaut) + **/ bool load_config_bool(LPCWSTR lpKeyName, bool bydefault=false) { return load_config_assoc(lpKeyName, aBoolTable, bydefault)!=0; } +/** + * Charge la taille/position de la fenêtre dans le fichier de configuration + * + * \param[in] lpKeyName nom de l'option rechercher + * \param[out] wpos structure retournant la taille trouvée, ou initialisée avec les valeurs par défaut + * \param[in] defL largeur par défaut, si pas trouvé + * \param[in] defH hauteur par défaut, si pas trouvé + **/ void load_config_winpos(LPCWSTR lpKeyName, WindowPos & wpos, long defL, long defH) { wchar_t position[32]; @@ -740,6 +1020,18 @@ } } +/** + * Cherche un paramètre dans le fichier de configuration \c "config.ini" + * + * \param[in] lpKeyName Clé dans le fichier de configuration recherchée + * \param[out] lpValue Valeur recherchée, devant déjà être initialisé + * \param[in] bufSize Nombre de caractères pouvant être retourné dans \a lpValue + * \param[in] nDefaultFolder Dossier par défaut à retourner, si on n'a rien trouvé + * (valeur CSIDL obligatoire: http://msdn.microsoft.com/en-us/library/bb762494(VS.85).aspx) + * \return Nombre de caractères copiés, sans tenir compte du caractère '\\0' + * \warning Si le dossier désiré demandé par \a nDefaultFolder n'existe pas (parce que la version est trop vieille, ou autre), + * celui-ci est remplacé par le dossier \c "Mes Documents" + **/ DWORD load_config_path(LPCWSTR lpKeyName, LPWSTR lpValue, DWORD bufSize, int nDefaultFolder) { wchar_t default_dir[MAX_PATH]; @@ -751,7 +1043,8 @@ } /** - * Lecture de la configuration depuis un fichier. + * Lecture de la configuration depuis le fichier de configuration + * se trouvant dans \c "%appdata%\poutchin TV Mod", ou dans le dossier actuel **/ void load_config(void) { @@ -785,6 +1078,7 @@ load_config_str(ini_filtre_audio, filtreAudio, _countof(filtreAudio)); load_config_str(ini_filtre_ac3, filtreAc3, _countof(filtreAc3)); load_config_str(ini_nom_ville, nomVille, _countof(nomVille)); + load_config_str(ini_nom_enregistrement, nom_enregistrement, _countof(nom_enregistrement), nom_enregistrement_default); exact_match = load_config_bool(ini_strict, true); sidChaineConfig = (WORD)load_config_int(ini_chaine_courante, 0); @@ -819,27 +1113,41 @@ /** * Chargement de la combo box 'hItm' à partir du fichier des noms de villes. + * + * \param[in] hItm handle du combo devant être remplie **/ void remplit_villes(HWND hItm) { - wchar_t strings[8192]; + // nombre de caractères à ajouter pour toutes les contenir en une fois + const int delta = 1024; + // nombre de caractères pour contenir les sections + size_t longueur = delta; + // contient toutes les sections du fichier INI + wchar_t *strings = new wchar_t[longueur]; + // Génère le nom complet des canaux wchar_t fileName[MAX_PATH]; wcscpy_s(fileName, _countof(fileName), pouchindir_prog); wcscat_s(fileName, _countof(fileName), scan_ini); - GetPrivateProfileSectionNames(strings, _countof(strings), fileName); + // Détermine la taille de la chaîne devant contenir toutes les sections + // car sinon, si le fichier INI contient trop de sections, on ne le lit pas les dernières + while( GetPrivateProfileSectionNames(strings, longueur, fileName) == longueur-2) { + // la taille du tableau est trop petit, on l'agrandie + delete [] strings; + longueur += delta; + strings = new wchar_t[longueur]; + } wchar_t * p = strings; + // Option pour scanner tous les canaux SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)L"Non précisée (scanne tous les canaux)"); while (*p != 0) { + // Ajoute l'entrée à la liste déroulante + SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)p); - if (wcscmp(general, p)) { - SendMessage(hItm, CB_ADDSTRING, 0, (LPARAM)p); - } - // trouve le prochain 0 while (*p != 0) { p++; @@ -851,6 +1159,9 @@ /** * Vérification de la validité de la configuration du tuner TNT. + * + * \retval true si le tuner configuré est valide + * \retval false si le tuner n'est pas valide **/ bool check_config(void) { Modifié: trunk/ini.h =================================================================== --- trunk/ini.h 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/ini.h 2008-11-28 20:51:01 UTC (rev 146) @@ -29,14 +29,24 @@ #include "utils.h" +/** + * Lit le fichier "scan.ini", qui décrit les différents émetteurs, ainsi que les canaux + * + * \param[in] ville nom de la section (émetteur) contenant les canaux à tester + **/ void lit_fichier_scan(wchar_t * ville); /** * Chargement du fichier des chaînes "chaines.xml". - * Retourne 0 en cas de succès, 1 si erreur. + * + * \retval 0 en cas de succès + * \retval 1 si erreur **/ int lit_chaines(); +/** + * Mémorise la liste des chaînes + **/ void sauve_chaines(void); /** @@ -50,60 +60,91 @@ void sauve_programmes(void); /** - * Sauvegarde de la configuration dans un fichier. + * Sauvegarde tous les paramètres de configuration **/ void save_config(void); /** - * Lecture de la configuration depuis un fichier. + * Lecture de la configuration depuis le fichier de configuration + * se trouvant dans \c "%appdata%\poutchin TV Mod", ou dans le dossier actuel **/ void load_config(void); /** * Chargement de la combo box 'hItm' à partir du fichier des noms de villes. + * + * \param[in] hItm handle du combo devant être remplie **/ void remplit_villes(HWND hItm); /** * Vérification de la validité de la configuration du tuner TNT. + * + * \retval true si le tuner configuré est valide + * \retval false si le tuner n'est pas valide **/ bool check_config(void); +/// Position de la fenêtre (enregistré) de PTVM extern WindowPos winPos; -// Priorité du processus courant selon la configuration +/// Priorité du processus courant selon la configuration extern DWORD configPriority; -// État de la fenêtre principale selon la configuration +/// État de la fenêtre principale selon la configuration extern EtatsFenetre configState; -// Nom de base du fichier définissant les villes et les canaux +/// Nom de base du fichier définissant les villes et les canaux extern wchar_t scan_ini[]; -// Structure avec constructeur, chargeant une chaîne de caractères et la protégeant -// en substituant les caractères non acceptables dans des noms de fichiers par le -// caractère fourni dans le paramètre "remplacement" : +/** + * Structure avec constructeur, chargeant une chaîne de caractères et la protégeant + * en substituant les caractères non acceptables dans des noms de fichiers par le + * caractère fourni dans le paramètre "remplacement" + **/ struct NomProtege { + /// Nom de fichier protégé char nom[64]; - // - // Constructeur : + /** + * Constructeur permettant de remplacer les caractères invalides (\"*:/<>?|) pour des noms de fichiers par un caractère valide + * + * \param[in] src nom du fichier à convertir + * \param[in] remplacement caractère de remplacement en cas de caractère invalide + **/ NomProtege(LPCSTR src, char remplacement); - // - // Extraction d'une copie Unicode : + /** + * Extraction d'une copie Unicode + * + * \param[out] lpWideCharStr chaîne unicode resultante + * \param[in] cchWideChar nombre de caractères pouvant contenir lpWideCharStr + * \return le nombre de caractères convertis, ou 0 en cas d'erreur + **/ int ToWide(LPWSTR lpWideCharStr, int cchWideChar) const; }; -// Structure avec constructeur, générant un nom de fichier complet incluant la date et l'heure -// courantes, à partir d'une chaîne de caractère préfixe et d'une extension : +/** + * Structure avec constructeur, générant un nom de fichier complet incluant la date et l'heure + * courantes, à partir d'une chaîne de caractère préfixe et d'une extension + **/ struct NomFichierAvecDate { + /// Nom complet du fichier généré wchar_t nom[MAX_PATH]; - // - // Constructeur : - NomFichierAvecDate(LPCWSTR dir, LPCSTR prefixe1, LPCSTR prefixe2, LPCSTR extension); - // - // Création : + /** + * Constructeur permettant de générer le nom du fichier d'enregistrement + * + * \param[in] dir dossier pour l'enregistrement du fichier + * \param[in] prefixe1 nom de l'enregistrement (seulement en cas de programmation d'enregistrement) + * \param[in] prefixe2 nom de la chaîne enregistrée + * \param[in] extension extention du fichier (permet de définir le type du fichier (BMP, MPG, TS, ...) + **/ + NomFichierAvecDate(LPCWSTR dir, LPCSTR prefixe1, LPCSTR prefixe2, LPCWSTR extension); + /** + * Ouvre le fichier (d'enregistrement) en écriture + * + * \return le handle d'ouverture du fichier + **/ HANDLE Create() const; }; @@ -122,3 +163,8 @@ * dans les enregistrements programmés, nécessitant une sauvegarde. **/ extern bool programmation_modifiee; + +/** + * Motifs pour les noms des enregistrements + **/ +extern wchar_t nom_enregistrement[MAX_PATH]; Modifié: trunk/internet.cpp =================================================================== --- trunk/internet.cpp 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/internet.cpp 2008-11-28 20:51:01 UTC (rev 146) @@ -143,7 +143,7 @@ // Récupère le status de la réponse wchar_t pStatus[4]; // Tableau recevant le résultat - DWORD dwStatusLength = 8; // Taille du tableau *2 (car UNICODE) + DWORD dwStatusLength = sizeof(pStatus); // Taille du tableau *2 (car UNICODE) HttpQueryInfo(this->hRequete, // Handle de la requète a vérifier HTTP_QUERY_STATUS_CODE, // Demande à récuprérer le code su status (200 => OK) @@ -157,7 +157,7 @@ } DWORD ConnexionInternet::RecupereFichier(LPBYTE contenu, DWORD *longueur) { - if (this->status != 200) { + if (this->status != HTTP_ERR_OK) { longueur = 0; return 0; } @@ -173,7 +173,7 @@ if (dwOctetsRestant == 0) break; - // Chaine contenant le contenu récupéré + // chaîne contenant le contenu récupéré BYTE *pContenu = (BYTE *)malloc(dwOctetsRestant + 1); DWORD dwOctetsLus; @@ -189,8 +189,7 @@ if (dwOctetsLus == 0) break; // Fin du fichier - for (DWORD i=0; igetStr(L"type", versTemp->type, _countof(versTemp->type)); - pNode->getStr(L"rev", versTemp->rev, _countof(versTemp->rev)); versTemp->major = pNode->getInt(L"major"); versTemp->minor = pNode->getInt(L"minor"); - + pNode->getStr(L"rev", versTemp->rev, _countof(versTemp->rev)); delete pNode; } @@ -1555,7 +1560,6 @@ // Récupère le chemin complet de l'exécutable GetModuleFileName(NULL, executable, sizeof(executable)); - // // Extrait la version interne des propriétés systèmes DWORD dwHandle = 0; // Ne sert à rien, mais bon @@ -1584,12 +1588,8 @@ strcat_s(version, _countof(version), versionActuelle); myprintf(L"\nVersion locale:\t\t%i.%i%S\nVersion beta:\t\t%i.%i%S\n\n", - major, - minor, - version, - beta.major, - beta.minor, - beta.rev); + major, minor, version, + beta.major, beta.minor, beta.rev); if (beta.major > major || (beta.major == major && beta.minor > minor) || @@ -1598,19 +1598,14 @@ L"Une nouvelle version de développement est disponible sur le site.", L"Nouvelle version !", MB_OK | MB_ICONINFORMATION); - delete [] byVersion; - return; + goto error; } } else { // Version de production myprintf(L"\nVersion locale:\t\t%i.%i%S\nVersion release:\t%i.%i%S\n\n", - major, - minor, - (char*)rcVersion.contenu, - release.major, - release.minor, - release.rev); + major, minor, (char*)rcVersion.contenu, + release.major, release.minor, release.rev); if (release.major > major || (release.major == major && release.minor > minor) || @@ -1619,8 +1614,7 @@ L"Une nouvelle version est disponible sur le site.", L"Nouvelle version !", MB_OK | MB_ICONINFORMATION); - delete [] byVersion; - return; + goto error; } } @@ -1628,6 +1622,14 @@ L"Vous disposez actuellement de la dernière version de Pouchin TV Mod.", L"Aucune mise à jour disponible", MB_ICONINFORMATION); + return; + +error: + // Nettoie les pointeurs avant de retourner + delete [] byVersion; + delete [] wsVersion; + return; + } else { MessageBox(hMainWnd, L"Le fichier de mise à jour n'est pas valide. Veuillez réessayer ultérieurement", @@ -1749,7 +1751,7 @@ // Sans couleur de fond :) SetBkMode(hdc, TRANSPARENT); - // Comme le numéro de la chaine et la chaine sont au même endroit, + // Comme le numéro de la chaîne et la chaîne sont au même endroit, // n'affiche que le plus récent des deux : if (show_prog && show_chaine) { if (last_chaine > last_zapping) @@ -1758,7 +1760,7 @@ show_chaine = false; } - // Affiche le nom de la chaine + programme en haut/droite + // Affiche le nom de la chaîne + programme en haut/droite if (show_prog && ixChaine_ok(ixChaineCourante)) { Chaine & canal = Canaux[ixChaineCourante]; @@ -1768,7 +1770,7 @@ "%s", canal.emis[0].nom); } - // Affiche les numéros saisis pour le choix des chaines en haut/droite + // Affiche les numéros saisis pour le choix des chaînes en haut/droite if (show_chaine && numeroChaineSaisi > 0) text_osd(hdc, rect.right, rect.top, TA_RIGHT, "%i", numeroChaineSaisi); @@ -1810,7 +1812,7 @@ if (SUCCEEDED(hr)) { - NomFichierAvecDate nom_fichier(screenshots_dir, NULL, Canaux[ixChaineCourante].nom, "bmp"); + NomFichierAvecDate nom_fichier(screenshots_dir, NULL, Canaux[ixChaineCourante].nom, L"bmp"); HANDLE file = nom_fichier.Create(); if (file != INVALID_HANDLE_VALUE) { @@ -2535,6 +2537,86 @@ return true; } +// Liste énumérative pour l'ordre des paramètres de la ligne de commande +enum eCmdOption { + cmd_minimize = 0, + cmd_fs, + cmd_max, + cmd_noborder, + cmd_normal, + cmd_recps, + cmd_rects, + cmd_chaine, + cmd_help, +}; + +/** + * Traite les options dans la ligne de commande + **/ +int * TraiteCmdLine() { + int nArgs = 0; + LPWSTR *szArgList = NULL; + + // Tableau contenant les paramètres + szArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs); + + LPWSTR szCmdLongOptions[] = { + L"--minimize", + L"--fs", + L"--maxi", + L"--noborders", + L"--normal", + L"--recps", + L"--rects", + L"--ch", + L"--help" + }; + int nbOptions = _countof(szCmdLongOptions); + int * valeurs = new int[nbOptions]; + ZeroMemory(valeurs, sizeof(int) * nbOptions); + + for (int i=1; i 0) && (cmd_channel <= (int)Canaux.size())){ - // Vérifie que la chaine passée en paramètre est connue - int temp = trouve_chaine_par_no((WORD)cmd_channel); + if ((cmdOptions[cmd_chaine] > 0) && (cmdOptions[cmd_chaine] <= (int)Canaux.size())){ + // Vérifie que la chaîne passée en paramètre est connue + int temp = trouve_chaine_par_no((WORD)cmdOptions[cmd_chaine]); if (temp != -1) zappe_index(temp); } - if (cmdOptions[cmd_recps].actif) { + if (cmdOptions[cmd_recps]) { if (start_record_ts(ixChaineCourante)>=0){ update_record_menus(hMainWnd); } } - if (cmdOptions[cmd_rects].actif) { + if (cmdOptions[cmd_rects]) { if (start_record_ps(ixChaineCourante,ixSonCourant)>=0){ update_record_menus(hMainWnd); } @@ -2935,6 +2932,9 @@ niData.update_state(); + // On n'a plus besoin des options de la ligne de commande, on libère donc la mémoire + delete [] cmdOptions; + // boucle qui traite les messages clavier while(GetMessage(&msg, NULL, 0, 0) ) { if (hSignalDlg!=NULL && IsDialogMessage(hSignalDlg, &msg)) @@ -2949,15 +2949,13 @@ DispatchMessage(&msg); } - // Si on demandé la mise à jour de MSN - if (use_msn) - { + // Si on demandé la mise à jour de MSN, on retire le titre modifié + if (use_msn) { // On cherche la fenêtre HWND msnui = FindWindow(L"MsnMsgrUIManager", NULL); // Si, msnui == NULL, MSN ne fonctionne pas ou le fenêtre est masquée (donc, pas de mise à jour) - if (msnui != NULL) - { + if (msnui != NULL) { // Si on l'a trouvée, on efface la musique indiquée sur MSN COPYDATASTRUCT msndata; msndata.dwData = 0x547; Modifié: trunk/parse.cpp =================================================================== --- trunk/parse.cpp 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/parse.cpp 2008-11-28 20:51:01 UTC (rev 146) @@ -135,7 +135,7 @@ myprintf(L"Transport stream id : %i\n", tsid); myprintf(L"Onid : %i\n", onid); - myprintf(L"chaines : \n"); + myprintf(L"chaînes : \n"); for (streamScanner se(sdt.entryRange(true)); !se; ++se) { Chaine canal; @@ -274,7 +274,7 @@ // le reste du traitement de la fonction est annulé. Mpeg2SectionsHandler handler; - unsigned prev_size = Canaux.size(); // Mémoriser le nombre de chaînes déjà identifiées à cet instant + size_t prev_size = Canaux.size(); // Mémoriser le nombre de chaînes déjà identifiées à cet instant unsigned i; myprintf(L"######################################\nscan de la fréquence : %i\n", freq.mhz); @@ -336,7 +336,7 @@ const Chaine & canal = Canaux[i]; if (canal.video_pid==0 && canal.video_type == vst_Unknown) { - //vire cette chaine + //vire cette chaîne myprintf(L"Destruction [%S/%S]\n", canal.groupe, canal.nom); Canaux.erase(Canaux.begin()+(i--)); } Modifié: trunk/record.cpp =================================================================== --- trunk/record.cpp 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/record.cpp 2008-11-28 20:51:01 UTC (rev 146) @@ -175,7 +175,7 @@ /** * Chercher l'index (dans 'enregistrements_actuels') des informations concernant - * la chaine d'index 'ixChaine' si celle-ci est en cours d'enregistrement. + * la chaîne d'index 'ixChaine' si celle-ci est en cours d'enregistrement. * Retourne -1 si elle ne l'est pas. **/ int getGrabberChaine(int ixChaine) @@ -235,7 +235,7 @@ int grab = getFreeGrabber(); if (grab>=0) { const Chaine & canal = Canaux[ixChaine]; - NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), canal.nom, "ts"); + NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), canal.nom, L"ts"); UINT16 video = canal.video_pid ; ISampleGrabberCB * pCallback = NULL; HANDLE hFile = nom_fichier.Create(); @@ -281,7 +281,7 @@ if (canal.video_type!=vst_MPEG2) // PS en MPEG2 seulement pour le moment return 0; - NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), canal.nom, "mpg"); + NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), canal.nom, L"mpg"); UINT16 video_pid = canal.video_pid; UINT16 audio_pid = canal.sons.tbl[ixSon].pid; ISampleGrabberCB * pCallback = NULL; @@ -317,7 +317,7 @@ { int grab = getFreeGrabber(); if (grab>=0) { - NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), "Transport Stream", "ts"); + NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), "Transport Stream", L"ts"); ISampleGrabberCB * pCallback = NULL; HANDLE hFile = nom_fichier.Create(); Modifié: trunk/record.h =================================================================== --- trunk/record.h 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/record.h 2008-11-28 20:51:01 UTC (rev 146) @@ -86,7 +86,7 @@ /** * Chercher l'index (dans 'enregistrements_actuels') des informations concernant - * la chaine d'index 'ixChaine' si celle-ci est en cours d'enregistrement. + * la chaîne d'index 'ixChaine' si celle-ci est en cours d'enregistrement. * Retourne -1 si elle ne l'est pas. **/ int getGrabberChaine(int ixChaine); Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/recprog.cpp 2008-11-28 20:51:01 UTC (rev 146) @@ -62,7 +62,7 @@ static SYSTEMTIME dtc_fin = {0}; /** - * On passe un SID de chaine en paramètre, + * On passe un SID de chaîne en paramètre, * et on retourne la fréquence du multiplex correspondant **/ static long getFrequence_par_sid(WORD sidChaine) Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2008-11-28 11:06:47 UTC (rev 145) +++ trunk/res.rc 2008-11-28 20:51:01 UTC (rev 146) @@ -171,30 +171,31 @@ CONTROL "Suspendre si minimisé",IDC_SUSPEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,20,262,10 CONTROL "Minimiser dans la zone de notification",IDC_SYSTEM_TRAY, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,37,262,10 - GROUPBOX "Audio",IDC_STATIC,7,57,276,27 - CONTROL "Utiliser l'AC3 par défaut",IDC_AC3_DEF,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,69,262,10 - GROUPBOX "Avancé",IDC_STATIC,7,85,2