From pouchintv-dev at baysse.fr Tue Nov 10 11:32:33 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: mar, 10 nov 2009 11:32:33 +0100 Subject: [Pouchintv-dev] [PouchinTVMod] lolo_32 | r206 - trunk Message-ID: <20091110103233.D47545F738@mail.baysse.fr> Author: lolo_32 Date: 2009-11-10 11:32:33 +0100 (mar 10 nov 2009) New Revision: 206 Modified: trunk/internet.cpp trunk/internet.h trunk/parse.h Log: internet.cpp, internet.h: ! Correction d'une fuite mémoire lors de l'envoie d'une requète + Ajout du support des requètes POST, avec envoie d'informations (mais ne fonctionne pas pour uploader des fichiers) + Ajout du support des requètes POST ou GET en HTTPS Modifié: trunk/internet.cpp =================================================================== --- trunk/internet.cpp 2009-09-06 00:30:13 UTC (rev 205) +++ trunk/internet.cpp 2009-11-10 10:32:33 UTC (rev 206) @@ -43,146 +43,299 @@ * Initialise les valeurs par défaut, l'User-Agent, la méthode à GET et le type de fichiers accepté * * \param[in] url url à interroger - **/ +**/ ConnexionInternet::ConnexionInternet(LPCTSTR url) : - m_url(0), - m_user_agent(0), - m_hConnection(0), + m_bChiffre(false), + m_methode(HTTP_METHODE_GET), + m_pszUrl(0), + m_pszServeur(0), + m_pszUserAgent(0), + m_hSession(0), + m_hConnexion(0), m_hRequete(0), - m_status(0), - m_taille(0), - m_recupere(0), - m_content_type(0) + m_dwStatus(0), + m_dwTaille(0), + m_dwRecupere(0), + m_pszContentType(0) { // Définition du "User Agent" (nom de l'application avec version détaillée) SetUserAgent(tstr_printf(TEXT("%s / %s"), szAppName, szAppVersion).c_str()); - SetMethodeGet(); - strcpy_T(this->m_accept_type, TEXT("*/*")); - - // Définit l'URL - if (url[0] != 0) - this->SetUrl(url); + if (url && url[0]) + SetUrl(url); } +/** + * Destructeur de la classe. Elle fait le ménage: + * # Ferme tous les handles laissés ou non ouverts pour Internet + * # Libère les chaînes de caractères de la classe + **/ ConnexionInternet::~ConnexionInternet() { // Libère le Handle de la requète if (this->m_hRequete) InternetCloseHandle(this->m_hRequete); // Libère le Handle de connexion - if (this->m_hConnection) - InternetCloseHandle(this->m_hConnection); + if (this->m_hConnexion) + InternetCloseHandle(this->m_hConnexion); + // Libère le Handle de session + if (this->m_hSession) + InternetCloseHandle(this->m_hSession); + // Libère l'url si alloué - if (this->m_url) - free(this->m_url); + if (this->m_pszUrl) + free(this->m_pszUrl); + + // Libère le nom du serveur si alloué + if (this->m_pszServeur) + free(this->m_pszServeur); + + // Libère l'User-Agent + if (this->m_pszUserAgent) + free(this->m_pszUserAgent); + + // Libère le Content-type (type de fichier) + if (this->m_pszContentType) + free(this->m_pszContentType); } /** + * Demande à établir une connexion sécurisée (en HTTPS) + * \param[in] chiffre Si true, la connexion sera établie en HTTPS + **/ +void ConnexionInternet::SetChiffree(bool chiffre) { + if (chiffre != this->m_bChiffre) { + // Avant de mémoriser l'option, on regarde s'il n'y a pas de connexions + // existantes avec l'ancien état + + if (this->m_hRequete) + InternetCloseHandle(this->m_hRequete), this->m_hRequete = 0; + + if (this->m_hConnexion) + InternetCloseHandle(this->m_hConnexion), this->m_hConnexion = 0; + + this->m_bChiffre = chiffre; + } +} + +/** + * Copie les informations internes, en libérant si besoin est le contenu de destination + * + * \param[in] destination variable destinataire. Si celle-ci est différente de NULL, elle sera effacée + * \param[in] source chaîne de caractères à mémoriser + **/ +void ConnexionInternet::SetInfo(LPTSTR *destination, LPCTSTR source) { + UINT longueur = strlen_T(source); + + // Efface l'ancien paramètre (si il existe) + if (*destination) + free(*destination); + + // Remplace par le nouveau + (*destination) = (LPTSTR)malloc(sizeof(TCHAR)*(longueur+1)); + strcpy_T((*destination), longueur+1, source); +} + +/** * Remplace l'User-Agent utilisé pour la requète * * \param[in] useragent User-Agent devant être utilisé **/ void ConnexionInternet::SetUserAgent(LPCTSTR useragent) { - UINT longueur = strlen_T(useragent); + SetInfo(&(this->m_pszUserAgent), useragent); +} - // Efface l'ancien (si spécifié - if (this->m_user_agent) - free(this->m_user_agent); - - // Remplace par le nouveau - this->m_user_agent = (LPTSTR)malloc(sizeof(TCHAR)*(longueur+1)); - strcpy_T(this->m_user_agent, longueur+1, useragent); +/** + * Indique l'url à utiliser pour passer la requète + * + * \param[in] serveur Serveur revevant la connexion (ex. pouchintv.baysse.fr) + * \param[in] url Url demandée (ex. /forum/) + * \retval 0 en cas d'erreur + **/ +int ConnexionInternet::SetUrl(LPCTSTR serveur, LPCTSTR url) { + SetInfo(&(this->m_pszServeur), serveur); + SetInfo(&(this->m_pszUrl), url); + return 1; } /** * Indique l'url à utiliser pour passer la requète * - * \param[in] url Url devant être questionnée + * \param[in] url Url complète demandée (ex. http://pouchintv.baysse.fr/forum/) + * \retval 0 en cas d'erreur **/ -void ConnexionInternet::SetUrl(LPCTSTR url) { - // Nombre de caractères dans l'url passée - UINT longueur = strlen_T(url); +int ConnexionInternet::SetUrl(LPCTSTR url) { - // Libère l'ancienne url si alloué - if (this->m_url) - free(this->m_url); + // on ne s'interesse qu'au hostname et à l'URL + URL_COMPONENTS urlc_explose = { + sizeof(urlc_explose) // dwStructSize + // Le reste à 0 (implicite) + }; + urlc_explose.dwHostNameLength = (DWORD)-1; + urlc_explose.dwUrlPathLength = (DWORD)-1; - // Stocke la nouvelle url - this->m_url = (LPTSTR)malloc( sizeof(TCHAR)*(longueur+1)); - strcpy_T(this->m_url, longueur+1, url); + // Explose l'URL passée + BOOL result = InternetCrackUrl( + url, // Url à exploser + 0, // taille de url + 0, // les flags ne sont pas utilisés + &urlc_explose); // structure recevant l'Url explosée + + if (result == TRUE) { + // Définit l'URL + LPTSTR hostname = (LPTSTR)malloc(sizeof(TCHAR)*(urlc_explose.dwHostNameLength+1)); + _tcsncpy_s(hostname, urlc_explose.dwHostNameLength+1, urlc_explose.lpszHostName, urlc_explose.dwHostNameLength); + this->SetUrl(hostname, urlc_explose.lpszUrlPath); + free(hostname); + + // Définit le chiffrage (le cas échéant) + SetChiffree( (urlc_explose.nScheme == INTERNET_SCHEME_HTTPS ? true : false) ); + } + return result; } /** * Envoie la connexion * - * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) - * \retval 0 en cas d'erreur - * \return une valeur de HTTP_ERR indiquant le status de la requète - * \todo Vérifier s'il n'y a pas de fuite de mémoire sur \p entete + * \param[in] donnees chaine de caractères à envoyer avec la requète + * \param[in] donnees_len longueur de donnees + * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) + * \retval 0 en cas d'erreur + * \return une valeur de HTTP_ERR indiquant le status de la requète + * \info si donnees != NULL, la requète sera envoyé en POST **/ -int ConnexionInternet::EnvoieRequete(DWORD debut) { - LPTSTR entete = 0; +int ConnexionInternet::EnvoieRequete(LPCSTR donnees, DWORD donnees_len, DWORD debut) { + LPCTSTR pszMethode = 0; - if (! this->m_hConnection) + if (! this->m_hConnexion) // Pas de connexion, on l'établit donc - this->EtablitConnexion(); + this->InitConnexion(); - if (!this->m_hConnection) + if (!this->m_hConnexion) return 0; // // On efface les données de la précédente connexion (si elle existent) // Réinitialise le status - this->m_status = 0; + this->m_dwStatus = 0; // Réinitialise la taille du fichier réponse - this->m_taille = 0; + this->m_dwTaille = 0; // Réinitialise la date ZeroMemory(&this->m_date, sizeof(this->m_date)); // Réinitialise le nombre d'octets récupérés - this->m_recupere = 0; + this->m_dwRecupere = 0; // Réinitialise le type de fichier - if (this->m_content_type != 0) - free(this->m_content_type); - this->m_content_type = 0; + if (this->m_pszContentType != 0) + free(this->m_pszContentType); + this->m_pszContentType = 0; - // Si une connexion existe, la fermer + // Si une requète existe, la fermer if (this->m_hRequete) InternetCloseHandle(this->m_hRequete); + // Teste la méthode utilisée pour envoyer la requète. + switch (this->m_methode) { + case HTTP_METHODE_GET: + pszMethode = TEXT("GET"); + break; + + case HTTP_METHODE_POST: + pszMethode = TEXT("POST"); + break; + } + + if (donnees) // n'a de sens que pour POST ou PUT + pszMethode = TEXT("POST"), this->m_methode = HTTP_METHODE_POST; + + // + // Finit de préparer la requète + LPCTSTR accept[2] = {TEXT("*/*"), NULL}; + this->m_hRequete = HttpOpenRequest( + this->m_hConnexion, // handle de la connexion précédement établie + pszMethode, // méthode à utiliser pour la requète + this->m_pszUrl, // adresse de la page devant traiter la requète + NULL, // version du protocole à utiliser (version par défaut ici) + NULL, // valeur du referer à utiliser (aucun ici) + accept, // fichiers acceptés + (this->m_bChiffre ? // Drapeaux différents en chiffré ou non + INTERNET_FLAG_SECURE: //Connexion chiffrée + 0), // pas de drapeau + 0); // contexte d'exécution (non utilisé ici) + + if (!this->m_hRequete) + return 0; + + if (this->m_bChiffre) { + DWORD dwFlags; + + dwFlags = + // On ignore le CA racine (au cas où il ne serait pas connu du poste) + // Il y a tout de même test du nom d'hote et correspondance dans le certificat + SECURITY_FLAG_IGNORE_UNKNOWN_CA | + // Ignore si le certificat est périmé + SECURITY_FLAG_IGNORE_CERT_DATE_INVALID; + + // Sauve les nouvelles options + InternetSetOption (this->m_hRequete, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) ); + } + // Ajoute un entête si des données sont spécifiées en plus + // c'est obligatoire pour indiquer au serveur qu'il doit attendre de recevoir les données + // avant de produire la réponse + if (donnees) { + LPCTSTR entete = TEXT("Content-Type: application/x-www-form-urlencoded"); + HttpAddRequestHeaders( + this->m_hRequete, // handle de la requete auquel ajouter l'entête Range + entete, // Entête content-type à rajouter + 47, // Longueur de l'entête à ajouter + HTTP_ADDREQ_FLAG_ADD | // Ajoute l'entête s'il n'existe pas + HTTP_ADDREQ_FLAG_REPLACE); // Remplace s'il existe + } + // Détermine si on fait une récupération partielle // Ajoute un en-tête de la forme "Range: bytes=1254725683-" if (debut != 0) { - TCHAR taille[15]; + LPTSTR entete = 0; + TCHAR taille[15]; _itot_s(debut, taille, _countof(taille), 10); // Récupération partielle UINT longueur = 15 /* Zone fixe de l'en tête*/ + strlen_T(taille); - entete = (LPTSTR)malloc(sizeof(TCHAR)*longueur); // Ceci est-il libéré quelque part ?? + entete = (LPTSTR)malloc(sizeof(TCHAR)*longueur); strcpy_T(entete, longueur, TEXT("Range: bytes=")); strcat_T(entete, longueur, taille); strcat_T(entete, longueur, TEXT("-")); + HttpAddRequestHeaders( + this->m_hRequete, // handle de la requete auquel ajouter l'entête Range + entete, // Entête range à rajouter + longueur, // longueur de l'entête à ajouter + HTTP_ADDREQ_FLAG_ADD | // Ajoute l'entête s'il n'existe pas + HTTP_ADDREQ_FLAG_REPLACE); // Remplace s'il existe + free(entete); } // // Envoie la requète - this->m_hRequete = InternetOpenUrl( - this->m_hConnection, // handle de la connexion précédement établie - this->m_url, // URL à ouvrir - entete, // En-tête ajoutés à la requète - (DWORD)-1L, // Taille de l'en-tête - INTERNET_FLAG_NO_AUTH | // Pas d'authentification - INTERNET_FLAG_NO_COOKIES | // Pas de cookies - INTERNET_FLAG_NO_UI | // Pas de fenêtre pour les cookies - INTERNET_FLAG_PRAGMA_NOCACHE | // Demande à ne pas utiliser le serveur proxy - INTERNET_FLAG_RELOAD, // Ne prends pas dans le cache local - 0); // Inutile (pour fonction de rappel seulement) + BOOL ret = HttpSendRequest( + this->m_hRequete, // handle de la requete préparée pour envoie + 0, // En-tête ajoutés à la requète + 0, // Taille de l'en-tête + (LPVOID)donnees, // Données à envoyer avec la requète (utilisé avec POST, PUT, ...). Si 0, ignoré + donnees_len); // Taille de données - if (!this->m_hRequete) - return 0; + if (ret != TRUE) { + switch (GetLastError()) { + case ERROR_INTERNET_TIMEOUT: + return HTTP_ERR_TIMEOUT; + case ERROR_INTERNET_SEC_CERT_CN_INVALID: + return HTTP_ERR_CNINVALID; + default: + return 0; + } + } + DWORD dwStructsLength = sizeof(DWORD); // @@ -190,7 +343,7 @@ HttpQueryInfo(this->m_hRequete, // Handle de la requète a vérifier HTTP_QUERY_STATUS_CODE | // Demande à récupérer le code su status (200 => OK) HTTP_QUERY_FLAG_NUMBER, // sous la forme de DWORD - &this->m_status, // Valeur du status + &this->m_dwStatus, // Valeur du status &dwStructsLength, // Taille du tampon NULL); // Inutilisé // @@ -198,7 +351,7 @@ HttpQueryInfo(this->m_hRequete, // Handle de la requète a vérifier HTTP_QUERY_CONTENT_LENGTH | // Demande à récupérer la taille du ficher HTTP_QUERY_FLAG_NUMBER, // sous la forme de DWORD - &this->m_taille, // Taille du fichier + &this->m_dwTaille, // Taille du fichier &dwStructsLength, // Taille du tampon NULL); // Inutilisé // @@ -207,11 +360,11 @@ HttpQueryInfo(this->m_hRequete, // Handle de la requète a vérifier HTTP_QUERY_LAST_MODIFIED | // Date et heure de modification du fichier HTTP_QUERY_FLAG_SYSTEMTIME, // sous la forme de SYSTEMTIME - &this->m_date, // Taille du fichier + &this->m_date, // Taille du fichier &dwStructsLength, // Taille du tampon NULL); // Inutilisé - return this->m_status; + return this->m_dwStatus; } /** @@ -220,23 +373,46 @@ * \retval 0 une erreur est survenue * \retval 1 tout s'est bien passé **/ -int ConnexionInternet::EtablitConnexion() { +int ConnexionInternet::InitConnexion() { + + if (! this->m_hSession) { + // Initialise la session + this->m_hSession = InternetOpen( + this->m_pszUserAgent, // User-agent + INTERNET_OPEN_TYPE_PRECONFIG, // Utilise le proxy de IE + NULL, // Inutile (voir ci-dessus) + NULL, // Inutile (voir ci-dessus) + 0); // Inutilisé + } + // Initialise la connexion - this->m_hConnection = InternetOpen( - this->m_user_agent, // User-agent - INTERNET_OPEN_TYPE_PRECONFIG, // Utilise le proxy de IE - NULL, // Inutile (voir ci-dessus) - NULL, // Inutile (voir ci-dessus) - 0); // Inutilisé + this->m_hConnexion = InternetConnect( + this->m_hSession, // Handle de session associé à la connexion + this->m_pszServeur, // Serveur auquel se connecter + (this->m_bChiffre ? // port à utiliser pour se connecter + INTERNET_DEFAULT_HTTPS_PORT : + INTERNET_DEFAULT_HTTP_PORT), + NULL, // nom d'utilisateur de connexion + NULL, // mot de passe de connexion + INTERNET_SERVICE_HTTP, // service à utiliser (HTTP, FTP ou gopher) - if (this->m_hConnection) + INTERNET_FLAG_KEEP_CONNECTION | // Maintenir la connexion ouverte entre 2 requètes + // TODO: est-ce utile ?????? + + INTERNET_FLAG_NO_AUTH | // Pas d'authentification + INTERNET_FLAG_NO_UI | // Pas de fenêtre pour les cookies + INTERNET_FLAG_PRAGMA_NOCACHE | // Demande à ne pas utiliser le serveur proxy + INTERNET_FLAG_RELOAD, // Ne prends pas dans le cache local + 0); // contexte (non utilisé) + + if (this->m_hConnexion) return 1; else return 0; } /** - * Lit le contenu de la réponse à la requète + * Lit le contenu de la réponse de la requète précédente * * \param[out] contenu tableau d'octets du fichiers lu * \param[in,out] longueur longueur de la variable contenue @@ -244,7 +420,7 @@ * \warning aucun caractère null ne sera ajouté à la fin de contenu **/ DWORD ConnexionInternet::RecupereFichier(LPBYTE contenu, DWORD *longueur) { - if (this->m_status != HTTP_ERR_OK && this->m_status != HTTP_ERR_OK_PARTIAL) { + if (this->m_dwStatus != HTTP_ERR_OK && this->m_dwStatus != HTTP_ERR_OK_PARTIAL) { // Il y a eu une erreur lors de la connexion // On arrête le parcour, et indique 0 octets lus *longueur = 0; @@ -266,7 +442,7 @@ DWORD dwOctetsLus; BOOL bResult = InternetReadFile(this->m_hRequete, contenu+lu, dwOctetsRestant, &dwOctetsLus); - this->m_recupere += dwOctetsLus; + this->m_dwRecupere += dwOctetsLus; if (!bResult) { // Erreur lors de la récup. Connection interrompue ??? lu = 0; @@ -290,38 +466,38 @@ * \param[in,out] longueur la taille de content maximale, et retourne le nombre d'octets copiés/necessaires **/ void ConnexionInternet::GetContentType(LPTSTR content, UINT *longueur) { - if (!this->m_content_type) { + if (!this->m_pszContentType) { // On récupère le type de fichier - this->m_content_type = (LPTSTR)malloc(sizeof(TCHAR)); + this->m_pszContentType = (LPTSTR)malloc(sizeof(TCHAR)); DWORD dwLength = sizeof(TCHAR); // Récupère la taille de l'en-tête HttpQueryInfo(this->m_hRequete, // Handle de la requète a vérifier - HTTP_QUERY_CONTENT_TYPE, // Type à récupérer - this->m_content_type, // Content-type + HTTP_QUERY_CONTENT_TYPE,// Type à récupérer + this->m_pszContentType, // Content-type &dwLength, // Taille du tampon (en octet) NULL); // Inutilisé // Alloue la bonne taille - free(this->m_content_type); - this->m_content_type = (LPTSTR)malloc(dwLength + sizeof(TCHAR)); + free(this->m_pszContentType); + this->m_pszContentType = (LPTSTR)malloc(dwLength + sizeof(TCHAR)); dwLength += sizeof(TCHAR); // Récupère les informations, et les stocke HttpQueryInfo(this->m_hRequete, // Handle de la requète a vérifier HTTP_QUERY_CONTENT_TYPE,// Type à récupérer - this->m_content_type, // Content-type + this->m_pszContentType, // Content-type &dwLength, // Taille du tampon NULL); // Inutilisé } // Fin de la récupération de l'en-tête - UINT size = strlen_T(this->m_content_type)+1; + UINT size = strlen_T(this->m_pszContentType)+1; if (*longueur < size) { *longueur = size; return; } - strcpy_T(content, *longueur, this->m_content_type); + strcpy_T(content, *longueur, this->m_pszContentType); *longueur = size; -} +} \ No newline at end of file Modifié: trunk/internet.h =================================================================== --- trunk/internet.h 2009-09-06 00:30:13 UTC (rev 205) +++ trunk/internet.h 2009-11-10 10:32:33 UTC (rev 206) @@ -36,6 +36,23 @@ class ConnexionInternet { public: + /// Constantes pour les résultats des requetes + static const enum HTTP_ERR { + HTTP_ERR_OK = 200, ///< Tout s'est bien passé + HTTP_ERR_OK_PARTIAL = 206, ///< Fichier partiel + HTTP_ERR_DROIT = 403, ///< Problème de droits d'accès + HTTP_ERR_INEXISTANT = 404, ///< Fichier inexistant + HTTP_ERR_INTERNE = 500, ///< Erreur interne du serveur + HTTP_ERR_TIMEOUT = 900, ///< La connexion s'est achevée, car elle a pris trop de temps + HTTP_ERR_CNINVALID, ///< Le CN du certificat ne correspont pas au nom du serveur + ///< (ex. www.ptvm.fr != www.ptv.fr) + }; + /// Constantes pour la méthode à utiliser pour la requète + static const enum HTTP_METHODE { + HTTP_METHODE_GET, ///< utilise la méthode GET + HTTP_METHODE_POST ///< utilise la méthode POST + }; + /** Initialise les valeurs par défaut, l'User-Agent, la méthode à GET et le type de fichiers accepté * \param[in] url url à interroger **/ @@ -43,28 +60,59 @@ ~ConnexionInternet(); + /** + * Définie la méthode à utiliser pour la connexion + * \param[in] methode Méthode à utiliser pour la connexion. + * Certaines permettent d'ajouter des paramètres + **/ + void SetMethode(HTTP_METHODE methode) {this->m_methode = methode;}; /** Indique l'url à utiliser pour passer la requète - * \param[in] url Url devant être questionnée + * \param[in] serveur Serveur revevant la connexion (ex. pouchintv.baysse.fr) + * \param[in] url Url demandée (ex. /forum/) + * \retval 0 en cas d'erreur **/ - void SetUrl(LPCTSTR _url); + int SetUrl(LPCTSTR serveur, LPCTSTR url); + /** Indique l'url à utiliser pour passer la requète + * \param[in] url Url complète demandée (ex. http://pouchintv.baysse.fr/forum/) + * \retval 0 en cas d'erreur + **/ + int SetUrl(LPCTSTR url); /** Remplace l'User-Agent utilisé pour la requète - * \param[in] useragent User-Agent devant être utilisé + * \param[in] useragent User-Agent devant être utilisé **/ void SetUserAgent(LPCTSTR useragent); + /** + * Demande à établir une connexion sécurisée (en HTTPS) + * \param[in] chiffre Si true, la connexion sera établie en HTTPS + **/ + void SetChiffree(bool chiffre); /** Envoie la connexion - * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) - * \retval 0 en cas d'erreur - * \return une valeur de HTTP_ERR indiquant le status de la requète + * \param[in] donnees chaine de caractères à envoyer avec la requète + * \warning il faut obligatoirement passer la chaine en CHAR, + * car si passée en WCHAR, les 0 sont aussi transmis + * \param[in] donnees_len longueur de donnees + * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) + * \retval 0 en cas d'erreur + * \return une valeur de HTTP_ERR indiquant le status de la requète **/ - int EnvoieRequete(DWORD debut = 0); + int EnvoieRequete(LPCSTR donnees = 0, DWORD donnees_len = 0, DWORD debut = 0); + /** Envoie la connexion + * \param[in] donnees chaine de caractères à envoyer avec la requète + * \param[in] donnees_len longueur de donnees + * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) + * \retval 0 en cas d'erreur + * \return une valeur de HTTP_ERR indiquant le status de la requète + * \info si donnees != NULL, la requète sera envoyé en POST + **/ + int EnvoieRequete(DWORD debut) {this->EnvoieRequete(0, 0, debut);}; /** Retourne le status de la connexion * \return le code status de la connexion **/ - int GetStatus() {return this->m_status;}; + int GetStatus() {return this->m_dwStatus;}; /** Retourne la taille du fichier * \return la taille du fichier **/ - DWORD GetTaille() {return this->m_taille;}; + DWORD GetTaille() {return this->m_dwTaille;}; /** Retourne le type de contenue * \param[out] content récupère le type de fichiers (ex. "text/html", "application/x-msdos-program") * \param[in,out] longueur la taille de content maximale, et retourne le nombre d'octets copiés/necessaires @@ -73,7 +121,7 @@ /** Retourne le nombre d'octets déjà récupérés * \return le nombre d'octets récupérés **/ - DWORD GetRestant() {return this->m_taille - this->m_recupere;}; + DWORD GetRestant() {return this->m_dwTaille - this->m_dwRecupere;}; /** Retourne la date/heure de modification du fichier * \return la date de modification du fichier **/ @@ -87,48 +135,44 @@ **/ DWORD RecupereFichier(LPBYTE contenu, DWORD *longueur); - /// Constantes pour les résultats des requetes - static const enum HTTP_ERR { - HTTP_ERR_OK = 200, ///< Tout s'est bien passé - HTTP_ERR_OK_PARTIAL = 206, ///< Fichier partiel - HTTP_ERR_DROIT = 403, ///< Problème de droits d'accès - HTTP_ERR_INEXISTANT = 404, ///< Fichier inexistant - HTTP_ERR_INTERNE = 500 ///< Erreur interne du serveur - }; - private: + /// Handle de la session + HINTERNET m_hSession; /// Handle de la connexion - HINTERNET m_hConnection; + HINTERNET m_hConnexion; /// Handle de la requète HINTERNET m_hRequete; + /// Connexion chiffrée ou pas + bool m_bChiffre; + /// Méthode de connexion (GET/POST ou autre) + HTTP_METHODE m_methode; /// User Agent utilisé - LPTSTR m_user_agent; - // Site de connexion (non utilisé avec InternetOpenUrl) - //wchar_t *site; - /// Méthode de connexion (GET/POST) - TCHAR m_methode[5]; - /// Type accepté (*/*) - TCHAR m_accept_type[4]; + LPTSTR m_pszUserAgent; + // Site de connexion + LPTSTR m_pszServeur; /// URL demandée - LPTSTR m_url; + LPTSTR m_pszUrl; /// Status de la requete - DWORD m_status; + DWORD m_dwStatus; /// Taille du fichier à télécharger - DWORD m_taille; + DWORD m_dwTaille; /// Date et heure de modification du fichier SYSTEMTIME m_date; /// Content-Type retourné par le serveur - LPTSTR m_content_type; + LPTSTR m_pszContentType; /// Octets récupérés - DWORD m_recupere; + DWORD m_dwRecupere; - /// Demande en GET - void SetMethodeGet() {strcpy_T(this->m_methode, TEXT("GET"));}; - /// Demande en POST - void SetMethodePost() {strcpy_T(this->m_methode, TEXT("POST"));}; + /// Initialise la connexion + int InitConnexion(); - /// Etablie la connexion - int EtablitConnexion(); + /** + * Copie les informations internes + * \param[in] destination variable destinataire. Si celle-ci est différente de NULL, elle sera effacée + * \param[in] source chaîne de caractères à mémoriser + **/ + void SetInfo(LPTSTR *destination, LPCTSTR source); + }; \ No newline at end of file Modifié: trunk/parse.h =================================================================== --- trunk/parse.h 2009-09-06 00:30:13 UTC (rev 205) +++ trunk/parse.h 2009-11-10 10:32:33 UTC (rev 206) @@ -152,8 +152,8 @@ * S'il est impossible de trouver un numéro selon ce critère (si tous les numéros "décalés" possibles * entre 1 et 999 sont pris), on retourne 0. * \param[in] nNumeroPropose Numéro proposé pour la chaîne. - * \retval Numéro trouvé (intervalle 1 à 999) - * \retval 0 si aucun numéro décalé disponible + * \retval Numéro trouvé (intervalle 1 à 999) + * \retval 0 si aucun numéro décalé disponible **/ UINT16 nouveau_numero_decale(UINT16 nNumeroPropose) const; @@ -161,8 +161,8 @@ * Attribution d'un nouveau numéro pour une nouvelle chaîne qui n'a pas de numéro proposé. * Cherche à attribuer ce numéro parmi les numéros disponibles, dans l'intervalle compris * entre la valeur de la variable \p autonum_undef et 999, puis entre 1 et \p autonum_undef. - * \retval Numéro trouvé (intervalle 1 à 999) - * \retval 0 si plus aucun numéro disponible (hypothèse assez improbable) + * \retval Numéro trouvé (intervalle 1 à 999) + * \retval 0 si plus aucun numéro disponible (hypothèse assez improbable) **/ UINT16 nouveau_numero_chaine() const; @@ -190,8 +190,10 @@ **/ void restaure_prefs(); - /// Transfert des numéros de chaîne de la NIT vers les chaînes qui viennent d'être ajoutées - /// \retval \p true si au moins une chaîne n'a pas reçu de numéro + /** + * Transfert des numéros de chaîne de la NIT vers les chaînes qui viennent d'être ajoutées + * \retval \p true si au moins une chaîne n'a pas reçu de numéro + **/ bool place_numeros(); /** From pouchintv-dev at baysse.fr Wed Nov 11 17:47:48 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: mer, 11 nov 2009 17:47:48 +0100 Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r207 - in trunk: . BaseClasses Icones/Locales Message-ID: <20091111164748.7FF145F75A@mail.baysse.fr> Author: gingko Date: 2009-11-11 17:47:47 +0100 (mer 11 nov 2009) New Revision: 207 Added: trunk/Icones/Locales/CLERMONT-1ERE.bmp trunk/config.h trunk/radio.bmp trunk/tv.bmp Modified: trunk/BaseClasses/streams.h trunk/Pouchin TV_2005.vcproj trunk/Pouchin TV_2008.vcproj trunk/base.h trunk/changelog.html trunk/channels.cpp trunk/channels.h trunk/graph.cpp trunk/graph.h trunk/ini.cpp trunk/ini.h trunk/internet.cpp trunk/internet.h trunk/main.cpp trunk/main.h trunk/parse.cpp trunk/record.cpp trunk/recprog.cpp trunk/recprog.h trunk/rendering.cpp trunk/rendering.h trunk/res.rc trunk/resource.h trunk/utils.cpp trunk/utils.h trunk/xml.cpp Log: Radios numériques belges et raccourci "dernière chaîne regardée". config.h, graph.h, base.h et fichiers de projet : * Ajout du fichier "config.h", destiné à contenir les options (#define) de configuration de compilation de l'application. La plupart des macros de ce type, initialement contenues dans "graph.h" ou "base.h", y sont transférées. channels.h, channels.cpp, main.cpp, resource.h : * Ajout d'un raccourci clavier, affecté par défaut à la touche "backspace", permettant de revenir sur la dernière chaîne affichée avant la chaîne courante (si au moins un changement a eu lieu depuis le démarrage de l'application). Un usage répété de ce raccourci a donc pour effet de provoquer un va-et-vient entre les deux dernières chaînes. * Prise en charge des radios numériques DVB (existantes en particulier en Belgique, à ce jour). Noter que, selon mes dernières informations, cette norme DVB ne sera vraisemblablement **pas** celle qui sera adoptée en France, et j'ignore si cette future norme pourra ou non être exploitée par Pouchin TV Mod. Noter également que l'enregistrement "PS" n'est actuellementpas pris en charge dans ce mode (d'ailleurs le terme "PS" n'aurait pas de sens dans ce cas). rendering.h, rendering.cpp, graph.cpp : * En cas de diffusion d'une radio numérique, ou bien en cas d'absence de codec vidéo pour la norme courante, l'affichage "CNullVideoRenderer", qui n'était précédemment utilisé qu'en cas d'absence de rendu vidéo, est maintenant activé. * Ajout de fonctions inline "GetVmrType" aux classes de rendu afin de pouvoir aisément identifier le rendu couramment utilisé. graph.h, graph.cpp, channels.cpp : * Remplacement des fonctions membres "debranche_son" et "branche_son", dans l'interface d'abstraction du graphe, par une fonction "change_son". Les deux anciennes fonctions subsistent, mais seulement de manière interne au module graphe. Le but de ceci est de rendre le changement de piste sonore plus abstrait, en vue d'améliorations futures. * Amélioration de la factorisation dans l'ajout des filtres "tuner" et "récepteur" BDA. recprog.h, recprog.cpp : * La synthèse des affichages d'heure de début et de fin de programmations de chaînes et déplacée dans des fonctions "inline" de la classe "Programme". main.cpp, res.rc, radio.bmp, tv.bmp, resource.h : * Les chaînes qui n'ont pas d'icône dédiée reçoivent maintenant une icône générique en niveaux de gris, différente selon qu'il s'agit de TV ou de radio numérique. main.cpp : * Correction d'un bug : l'option qui permettait de faire en sorte que les touches multimédia ne soient plus gérées ne fonctionnait pas. utils.h, utils.cpp, ini.h, ini.cpp, main.cpp : * La classe "RcdataResource" est renommée en "RawResource", déplacée dans "utils.h" et "utils.cpp", et modifiée de manière à pouvoir prendre en charge des formats de ressources autres que "RT_RCDATA". utils.h, utils.cpp, xml.cpp : * Les fonctions "ConvertChar2UTF8" prennent maintenant aussi en charge la conversion, si leur argument "for_sgml" est "true", de certains caractères en entités SGML. Ceci n'est donc plus effectué dans "xml.cpp". internet.h, internet.cpp : * Petits ajustements dans les commentaires destinés à "Doxygen". main.h : * Commentaires ajoutés. Ajout d'une icône de chaîne locale "CLERMONT-1ERE.bmp". Modifié: trunk/BaseClasses/streams.h =================================================================== --- trunk/BaseClasses/streams.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/BaseClasses/streams.h 2009-11-11 16:47:47 UTC (rev 207) @@ -193,7 +193,7 @@ #include // audio filter device error event codes - +// Removed because useless and boring (Gingko) //#else // #ifdef DEBUG // #pragma message("STREAMS.H included TWICE") Ajouté: trunk/Icones/Locales/CLERMONT-1ERE.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/Icones/Locales/CLERMONT-1ERE.bmp ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Modifié: trunk/Pouchin TV_2005.vcproj =================================================================== --- trunk/Pouchin TV_2005.vcproj 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/Pouchin TV_2005.vcproj 2009-11-11 16:47:47 UTC (rev 207) @@ -900,6 +900,10 @@ > + + @@ -1034,6 +1038,10 @@ > + + @@ -1042,6 +1050,10 @@ > + + Modifié: trunk/Pouchin TV_2008.vcproj =================================================================== --- trunk/Pouchin TV_2008.vcproj 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/Pouchin TV_2008.vcproj 2009-11-11 16:47:47 UTC (rev 207) @@ -893,6 +893,10 @@ > + + @@ -1027,6 +1031,10 @@ > + + @@ -1035,6 +1043,10 @@ > + + Modifié: trunk/base.h =================================================================== --- trunk/base.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/base.h 2009-11-11 16:47:47 UTC (rev 207) @@ -61,6 +61,9 @@ // source. Voir commentaires dans le fichier atlbase_ptvm.h. #include "vstudio_edition.h" +// Inclusion des macros d'options de compilation +#include "config.h" + #if !defined(COMPILER_EDITION_VCEXPRESS) #pragma warning(push) #pragma warning(disable:4995) // Quelques inconsistances de Microsoft dans les en-têtes ATL @@ -104,23 +107,6 @@ #include "console.h" - /// on exporte le graphe DShow - #define EXPORT_GRAPH 1 - -#ifdef _DEBUG - /// Enregistrer DShow - #define LOG_DSHOW 1 -#else - /// on ne logue pas les évènements DShow - #define LOG_DSHOW 0 -#endif - -#ifndef USE_LOGITECH_LCD // (ignorer si défini par le projet) - /// Activation du LCD Logitech si la macro est définie - #define USE_LOGITECH_LCD - #undef USE_LOGITECH_LCD // (#undef pour que Doxygen accepte de documenter cette macro) -#endif - /// Nombre max de chaînes #define NB_MAX_CHAINES 500 Modifié: trunk/changelog.html =================================================================== --- trunk/changelog.html 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/changelog.html 2009-11-11 16:47:47 UTC (rev 207) @@ -56,6 +56,22 @@

Changements réalisés pour la version 0.5

+
0.5.207 (expérimentale, publiée dans le forum le 11 novembre 2009) :
+
    +
  • Ajout de la prise en charge des radios numériques DVB telles que celles qu'on peut avoir en Belgique.
  • +
  • Ajout d'un raccourci clavier (backspace par défaut) permettant de revenir sur la chaîne précédemment + regardée (s'il en existait une).
  • +
  • En cas d'absence d'icône spécifique pour une chaîne donnée, une icône générique en niveaux de gris + est maintenant affichée.
  • +
  • En cas d'absence d'affichage vidéo (pas de codec ou bien chaîne radio), un rendu générique (avec une croix, + bleue barrant l'écrant) est affiché, à la manière de ce qui existait déjà précédemment quand on désactivait le + rendu vidéo.
  • +
  • Correction d'un bug : l'option de désactivation de la prise en charge des touches multimédia + ne fonctionnait pas correctement.
  • +
  • Icône Clermont 1ère ajoutée.
  • +
+
+
0.5.205 (expérimentale, publiée via le service de mise à jour le 6 septembre 2009) :
  • Correction d'un bug : en cas d'extinction de l'ordinateur sans quitter le logiciel, Modifié: trunk/channels.cpp =================================================================== --- trunk/channels.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/channels.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -40,6 +40,7 @@ int ixChaineAvance = -1; /*!< Index de la chaîne pendant les transitions de zapping (normalement identique à \p ixChaineCourante, sauf entre la sélection d'une chaîne et l'application de cette sélection) */ +int ixDerniereChaine = -1; //!< Mémorisation dernière chaîne regardée (avant chaîne courante) int ixSonCourant = 0; //!< Index de la piste sonore couramment utilisée static bool suspendu = true; //!< \p true si vidéo et audio suspendus (à l'initialisation, //!< ou si minimisé + \p suspend_minimized) @@ -114,6 +115,8 @@ case vst_H264_encrypted: return TEXT("Crypté"); } + if (sons.nbr > 0) + return TEXT("Audio"); return TEXT("Inconnu"); } @@ -480,7 +483,7 @@ bProt = true; if (suspendu && ixChaine_ok(ixChaineCourante)) { - myprintf(BOLD(TEXT("Branchement des sorties audio et vidéo")) EOL); + myprintf(BOLD(TEXT("Branchement des sorties audio et vidéo")) EOL); HRESULT hr = Canaux[ixChaineCourante].branche(reset_son); @@ -508,8 +511,7 @@ if (ixSon>=0 && ixSondebranche_son(); - pGraph->branche_son(son.pid, son.type); + pGraph->change_son(son.pid, son.type); ixSonCourant = ixSon; if (pOSD) @@ -549,6 +551,8 @@ return S_FALSE; // On ne change pas de fréquence si enregistrement en cours } + int ixSauveChaine = ixChaineCourante; + ixChaineCourante = -1; // doit être égal à -1 pendant les transitions (à cause du filtre PMT) if (chaine_differente) @@ -571,7 +575,14 @@ myprintf(CMyP ERRX(TEXT("Erreur(s) change_frequence : %s")), !strErr.empty(), strErr.c_str()); } - ixChaineCourante = ixChaine_ok(ixChaine) ? ixChaine : -1; + if (ixChaine_ok(ixChaine)) { + // Sauvegarde de la chaîne qu'on abandonne (pour zapping en va-et-vient) + if (ixChaine_ok(ixSauveChaine) && ixSauveChaine != ixChaine) + ixDerniereChaine = ixSauveChaine; + ixChaineCourante = ixChaine; + } else + ixChaineCourante = -1; + ixChaineAvance = ixChaineCourante; // Ne reconnecter l'interface que si elle n'était pas suspendue : Modifié: trunk/channels.h =================================================================== --- trunk/channels.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/channels.h 2009-11-11 16:47:47 UTC (rev 207) @@ -222,6 +222,14 @@ * valeur par défaut, selon préférences globales de l'utilisateur **/ HRESULT branche(bool reset_son) const; + + /// Déterminer s'il s'agit d'une chaîne audio (radio numérique) + bool isAudio() const { + return video_type == vst_Unknown && video_pid == 0 && sons.nbr > 0;} + + /// Déterminer si l'enregistrement en mode PS est disponible + bool isPsRecordAvailable() const { + return video_type==vst_MPEG2;} // PS en MPEG2 seulement pour le moment }; /// Type tableau des chaînes @@ -292,7 +300,7 @@ extern int ixChaineAvance; /*!< Index de la chaîne pendant les transitions de zapping, ainsi qu'en phase de démarrage (normalement identique à \p ixChaineCourante, sauf entre la sélection d'une chaîne et l'application de cette sélection) */ - +extern int ixDerniereChaine; //!< Mémorisation dernière chaîne regardée (avant chaîne courante) extern int ixSonCourant; //!< Index de la piste sonore couramment utilisée /** Ajouté: trunk/config.h =================================================================== --- trunk/config.h (rev 0) +++ trunk/config.h 2009-11-11 16:47:47 UTC (rev 207) @@ -0,0 +1,87 @@ +/* + * options.h + * Copyright (C) 2009 gingko - http://gingko.homeip.net/ + * + * This file is part of Pouchin TV Mod, a free DVB-T viewer. + * See http://pouchintv.baysse.fr/ for updates. + * + * Pouchin TV Mod 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 Mod 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 + * + * + * Most files of this project have been changed from the Pouchin TV + * project (Copyright (C) 2006 Pouchin ), + * to use with a modified version of this software. + * See http://pouchinteve.free.fr/ for the original project. + */ + +#pragma once + +/** \defgroup MiscTestMacros Macros d'expérimentations diverses + * Macros destinées à activer ou désactiver des fonctionnalités du logiciel, + * à titre permanent ou bien en vue d'expérimentations pour des évolutions futures, + * ou encore pour pouvoir restaurer d'anciennes fonctionnalités. + * @{ */ + +// ==================================================================================== +// Options diverses +// ==================================================================================== + +#ifndef USE_LOGITECH_LCD // (ignorer si défini par le projet) + /// Activation du LCD Logitech si la macro est définie + #define USE_LOGITECH_LCD + #undef USE_LOGITECH_LCD // (#undef pour que Doxygen accepte de documenter cette macro) +#endif + +// ==================================================================================== +// Options liées au graphe +// ==================================================================================== + +#define USE_AUTO_RETUNE 1 //!< Resyntonisation automatique + +#define USE_PMTFILTER 1 //!< Activation/désactivation filtre PMT + +#define EXPORT_GRAPH 1 //!< Exportation du graphe (pour Graphedit) + +/** + * Macro visant à simuler l'existence d'une radio numérique RNT du style de celles qui existent + * en Belgique : si sa valeur est différente de 0, alors elle est un numéro de PID vidéo qui ne + * sera PAS reconnu (par exemple 165 pour Gulli en France à Paris), et la chaîne correspondante + * sera vue comme si elle était une radio. + **/ +#ifdef _DEBUG + #define TEST_RNT_RADIO 165 +#else + #define TEST_RNT_RADIO 0 +#endif + +/** + * Macro facilitant les essais de désactivation d'une fonctionnalité relativement + * peu susceptible d'être utilisée, mais susceptible de provoquer des instabilités + * quand elle l'est, puisqu'elle induit la possibilité que soient utilisés des + * codecs qui n'ont pas été choisis en cas d'échec de ceux qui l'ont été. + **/ +#define AUTO_RENDER 0 /*!< \brief Recherche automatique de filtres appropriés en + cas d'échec de l'insertion du filtre initialement prévu */ +#ifdef _DEBUG + /// Enregistrer DShow + #define LOG_DSHOW 1 +#else + /// on ne logue pas les évènements DShow + #define LOG_DSHOW 0 +#endif + +/** @} */ + +// ==================================================================================== Modifié: trunk/graph.cpp =================================================================== --- trunk/graph.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/graph.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -442,7 +442,7 @@ return bRunning;} /// Construction du graphe - virtual HRESULT Build(); + virtual HRESULT Build(); #ifdef _DEBUG virtual tstring get_graph_state(); @@ -741,7 +741,6 @@ CComPtr pBDAFreq; #endif - VideoStreamType ePrevVideoType; //!< Type de flux vidéo couramment utilisé (pour pouvoir //!< détecter quand changer de codec) bool bSuspended; //!< \p true si sorties médias suspendues @@ -833,6 +832,13 @@ virtual void debranche_son(); /** + * Changement de piste sonore. + * \param[in] pid PID de la piste à brancher + * \param[in] type Type de la piste audio + **/ + virtual HRESULT change_son(UINT16 pid, TrackStreamType type); + + /** * \brief Vérification de l'existence d'un dialogue de propriétés pour filtre * * \param[in] eFltType Type du filtre pour lequel l'existence du dialogue doit être vérifiée @@ -920,7 +926,7 @@ { FilterData sNetworkProvider; - virtual HRESULT AddProvider(CComPtr & pLastAddedFilter); + virtual HRESULT AddProvider(CComPtr & pLastAddedFilter); virtual HRESULT AddDataFilters(IMpeg2Demultiplexer & iMp2Demux); #if USE_STD_NETWP_TUNSPC @@ -935,7 +941,7 @@ public: /// Constructeur CMicrosoftTunerGraph() : - sNetworkProvider(TEXT("Microsoft DVB-T Network Provider"), CLSID_DVBTNetworkProvider) + sNetworkProvider(TEXT("Microsoft DVB-T Network Provider"), CLSID_DVBTNetworkProvider) {} /// Destructeur @@ -1086,9 +1092,9 @@ * \param[out] pOutPin Interface sur la broche trouvée ou créé **/ HRESULT CPTvM_TunerGraph::get_output_pin(IMpeg2Demultiplexer & iMp2Demux, - DecoderData & sDData, - bool bFindExisting, - CComPtr & pOutPin) + DecoderData & sDData, + bool bFindExisting, + CComPtr & pOutPin) { HRESULT hr; @@ -1528,46 +1534,34 @@ CSearchByCategory_Get(KSCATEGORY_BDA_NETWORK_TUNER, nom_tuner, pNetworkTuner).Do(); + hr = AddFilterToGraph(pNetworkTuner, nom_tuner); + if (FAILED(hr)) + return erreur(TEXT("Échec de l'insertion du filtre Tuner"), hr); + + // connect Tuner + hr = connect_filters(pLastAddedFilter, pNetworkTuner); + if (FAILED(hr)) + return erreur(TEXT("Tuner TNT non compatible, veuillez effacer \"config.ini\" et redémarrer"), hr); + CompatResult eCompat = filtre_compat(pNetworkTuner); + if (eCompat == compat_Tuner) { - // PCI CComPtr pReceiverComponent; - hr = AddFilterToGraph(pNetworkTuner, nom_tuner); - if (FAILED(hr)) - return erreur(TEXT("Échec de l'insertion du filtre Tuner"), hr); - CSearchByCategory_Get(KSCATEGORY_BDA_RECEIVER_COMPONENT, nom_receiver, pReceiverComponent).Do(); hr = AddFilterToGraph(pReceiverComponent, nom_receiver); if (FAILED(hr)) return erreur(TEXT("Échec de l'insertion du filtre Récepteur"), hr); - // connect Tuner - hr = connect_filters(pLastAddedFilter, pNetworkTuner); - if (FAILED(hr)) - return erreur(TEXT("Tuner TNT non compatible, veuillez effacer \"config.ini\" et redémarrer"), hr); - // connect Receiver hr = connect_filters(pNetworkTuner, pReceiverComponent); if (FAILED(hr)) return erreur(TEXT("Récepteur TNT non compatible, veuillez effacer \"config.ini\" et redémarrer"), hr); pLastAddedFilter = pReceiverComponent; // Mémoriser pour connexion suivante - } else if (eCompat == compat_Receiver) { - // USB - - // connect USB - hr = AddFilterToGraph(pNetworkTuner, nom_tuner); - if (FAILED(hr)) - return erreur(TEXT("Échec de l'insertion du filtre Tuner USB"), hr); - - hr = connect_filters(pLastAddedFilter, pNetworkTuner); - if (FAILED(hr)) - return erreur(TEXT("Tuner USB non compatible, veuillez effacer \"config.ini\" et redémarrer"), hr); - + } else if (eCompat == compat_Receiver) pLastAddedFilter = pNetworkTuner; // Mémoriser pour connexion suivante - } hr = pNetworkTuner.QueryInterface(&pBDAControl); @@ -1688,7 +1682,7 @@ if (FAILED(hr)) return erreur(TEXT("Erreur lors de la création du graphe"), hr); - hr = init_vmr(); + hr = init_vmr(eVideoType==vst_Unknown); // Une erreur à l'initialisation du VMR n'est pas interruptive : le reste du // graphe doit pouvoir continuer à fonctionner (néanmoins, inutile de tenter @@ -1826,6 +1820,17 @@ } /** + * Changement de piste sonore. + * \param[in] pid PID de la piste à brancher + * \param[in] type Type de la piste audio + **/ +HRESULT CPTvM_TunerGraph::change_son(UINT16 pid, TrackStreamType type) +{ + debranche_son(); + return branche_son(pid, type); +} + +/** * Sélection d'un (nouveau ou pas) codec vidéo * \param[in] eVideoType Codec à sélectionner * \param[in] video_pid si != 0, branchement de ce PID au démultiplexeur en même temps @@ -1836,9 +1841,18 @@ switch (eVideoType) { + case vst_Unknown: // audio seul, par exemple ... + if (pVMR && ePrevVideoType!=vst_Unknown) { + if (FAILED(hr = switch_codec(NULL))) + return hr; + ePrevVideoType = vst_Unknown; + } + hr = S_OK; + break; + case vst_MPEG2: if (pVMR && ePrevVideoType!=vst_MPEG2) { - if (FAILED(hr = switch_codec(sMp2vCodec))) + if (FAILED(hr = switch_codec(&sMp2vCodec))) return hr; ePrevVideoType = vst_MPEG2; } @@ -1848,7 +1862,7 @@ case vst_H264: if (pVMR && ePrevVideoType!=vst_H264) { - if (FAILED(hr = switch_codec(sH264Codec))) + if (FAILED(hr = switch_codec(&sH264Codec))) return hr; ePrevVideoType = vst_H264; } @@ -1874,14 +1888,13 @@ HRESULT hr = E_FAIL; // valeur par défaut if (bSuspended) { - if (video_pid) - hr = select_video_codec(eVideoType, video_pid); + hr = select_video_codec(eVideoType, video_pid); branche_son(audio_pid, eAudioType); -#if USE_PMTFILTER + #if USE_PMTFILTER // pmt hr = sPMT_Filter.branche_pid(pmt_pid); -#endif + #endif bSuspended = false; } return hr; @@ -1896,9 +1909,9 @@ sMp2vCodec.debranche_pids(); sH264Codec.debranche_pids(); debranche_son(); -#if USE_PMTFILTER + #if USE_PMTFILTER sPMT_Filter.debranche_pids(); -#endif + #endif bSuspended = true; } } Modifié: trunk/graph.h =================================================================== --- trunk/graph.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/graph.h 2009-11-11 16:47:47 UTC (rev 207) @@ -34,32 +34,7 @@ #include // ==================================================================================== -// Expérimentations sur le graphe -// ==================================================================================== -/** \defgroup GraphTestMacros Macros d'expérimentations sur le graphe - * Macros destinées à activer ou désactiver des fonctionnalités du graphe, - * à titre permanent ou bien en vue d'expérimentations pour des évolutions futures, - * ou encore pour pouvoir restaurer d'anciennes fonctionnalités. - * @{ */ - -#define USE_AUTO_RETUNE 1 //!< Resyntonisation automatique - -#define USE_PMTFILTER 1 //!< Activation/désactivation filtre PMT - -/** - * Macro facilitant les essais de désactivation d'une fonctionnalité relativement - * peu susceptible d'être utilisée, mais susceptible de provoquer des instabilités - * quand elle l'est, puisqu'elle induit la possibilité que soient utilisés des - * codecs qui n'ont pas été choisis en cas d'échec de ceux qui l'ont été. - **/ -#define AUTO_RENDER 0 /*!< \brief Recherche automatique de filtres appropriés en - cas d'échec de l'insertion du filtre initialement prévu */ - -/** @} */ - -// ==================================================================================== - extern CLSID MEDIASUBTYPE_DOLBY_DDPLUS; // ==================================================================================== @@ -201,18 +176,13 @@ virtual void debranche_medias() = 0; /** - * Branchement d'une piste sonore. + * Changement de piste sonore. * \param[in] pid PID de la piste à brancher * \param[in] type Type de la piste audio **/ - virtual HRESULT branche_son(UINT16 pid, TrackStreamType type) = 0; + virtual HRESULT change_son(UINT16 pid, TrackStreamType type) = 0; /** - * Débranchement de toutes les pistes sonores - **/ - virtual void debranche_son() = 0; - - /** * \brief Vérification de l'existence d'un dialogue de propriétés pour filtre * * \param[in] eFltType Type du filtre pour lequel l'existence du dialogue doit être vérifiée Modifié: trunk/ini.cpp =================================================================== --- trunk/ini.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/ini.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -59,6 +59,7 @@ // Changement de chaînes {IDM_CHAN_AUG, TEXT("Chaîne suivante"), TEXT("Chaîne suiv"), {false, false, false, VK_DOWN}}, {IDM_CHAN_DIM, TEXT("Chaîne précédente"), TEXT("Chaîne préc"), {false, false, false, VK_UP}}, + {IDM_LAST_CHAN, TEXT("Retour dernière chaîne vue"), TEXT("Chaîne retour"), {false, false, false, VK_BACK}}, {IDM_CHAN_AUG_MPX, TEXT("Chaîne suivante du multiplex"), TEXT("Chaîne suiv"), {true, false, false, VK_DOWN}}, {IDM_CHAN_DIM_MPX, TEXT("Chaîne précédente du multiplex"), TEXT("Chaîne préc"), {true, false, false, VK_UP}}, {IDM_CHAN_TUNE, TEXT("Forcer une resyntonisation"), TEXT("Chaîne Resyntoniser"),{false, true, false, TEXT('F')}}, @@ -840,46 +841,6 @@ } // ==================================================================================== -// Ressources -// ==================================================================================== - -/** - * Extrait une resource de type RCData du fichier. Charge également la taille allouée. - * \param[in] idRessource Identifiant de la resource. - * \retval \p true en cas de succès, \p false en cas d'échec. - **/ -bool RcdataResource::Extraction(UINT idRessource) -{ - HRSRC hRcdataResource = FindResource(hAppInstance, MAKEINTRESOURCE(idRessource), RT_RCDATA); - bool bRes = false; - - if (hRcdataResource != NULL) { - taille = SizeofResource(hAppInstance, hRcdataResource); - // Charge la ressource identifiée - HGLOBAL hRcdataCharge = LoadResource(hAppInstance, hRcdataResource); - - if (hRcdataCharge != NULL) { - // Bloque la ressource en mémoire pour utilisation - LPBYTE RcdataRes = (LPBYTE)LockResource(hRcdataCharge); - - if (RcdataRes != NULL) { - // Tout s'est bien passé: on peut utiliser la resource - contenu = new BYTE[taille + 1]; - ZeroMemory(contenu, taille + 1); - for (int i=0; i(contenu);} - - ~RcdataResource() { - if (contenu) - delete [] contenu; - } -}; - /** * Détermine si une définition de configuration est définie comme "Aucun" ("[Null]") ou * "non défini" (chaîne vide). @@ -532,12 +504,12 @@ static inline LPWSTR find_invalid(LPWSTR str) { return wcspbrk(str, L"\"*/:<>?\\|");} - void Protege(T remplacement) { /** - * Substitution, dans \p nom, des caractères invalides (\"*:/<>?|) + * Substitution, dans \p nom, des caractères invalides * pour des noms de fichiers par un caractère valide * \param[in] remplacement caractère de remplacement en cas de caractère invalide **/ + void Protege(T remplacement) { T * pcar; while ((pcar = find_invalid(nom)) != NULL) @@ -546,7 +518,7 @@ /** - * Constructeur permettant de remplacer les caractères invalides (\"*:/<>?|) + * Constructeur permettant de remplacer les caractères invalides * pour des noms de fichiers par un caractère valide * * \param[in] src nom de fichier à convertir Modifié: trunk/internet.cpp =================================================================== --- trunk/internet.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/internet.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -195,15 +195,15 @@ return result; } -/** - * Envoie la connexion - * +/** Envoie la connexion * \param[in] donnees chaine de caractères à envoyer avec la requète + * \warning il faut obligatoirement passer la chaine en CHAR, + * car si passée en WCHAR, les 0 sont aussi transmis * \param[in] donnees_len longueur de donnees * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) * \retval 0 en cas d'erreur * \return une valeur de HTTP_ERR indiquant le status de la requète - * \info si donnees != NULL, la requète sera envoyé en POST + * \note si donnees != NULL, la requète sera envoyé en POST **/ int ConnexionInternet::EnvoieRequete(LPCSTR donnees, DWORD donnees_len, DWORD debut) { LPCTSTR pszMethode = 0; Modifié: trunk/internet.h =================================================================== --- trunk/internet.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/internet.h 2009-11-11 16:47:47 UTC (rev 207) @@ -61,31 +61,36 @@ ~ConnexionInternet(); /** - * Définie la méthode à utiliser pour la connexion + * Définit la méthode à utiliser pour la connexion * \param[in] methode Méthode à utiliser pour la connexion. * Certaines permettent d'ajouter des paramètres **/ void SetMethode(HTTP_METHODE methode) {this->m_methode = methode;}; + /** Indique l'url à utiliser pour passer la requète * \param[in] serveur Serveur revevant la connexion (ex. pouchintv.baysse.fr) * \param[in] url Url demandée (ex. /forum/) * \retval 0 en cas d'erreur **/ int SetUrl(LPCTSTR serveur, LPCTSTR url); + /** Indique l'url à utiliser pour passer la requète * \param[in] url Url complète demandée (ex. http://pouchintv.baysse.fr/forum/) * \retval 0 en cas d'erreur **/ int SetUrl(LPCTSTR url); + /** Remplace l'User-Agent utilisé pour la requète * \param[in] useragent User-Agent devant être utilisé **/ void SetUserAgent(LPCTSTR useragent); + /** * Demande à établir une connexion sécurisée (en HTTPS) * \param[in] chiffre Si true, la connexion sera établie en HTTPS **/ void SetChiffree(bool chiffre); + /** Envoie la connexion * \param[in] donnees chaine de caractères à envoyer avec la requète * \warning il faut obligatoirement passer la chaine en CHAR, @@ -94,34 +99,38 @@ * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) * \retval 0 en cas d'erreur * \return une valeur de HTTP_ERR indiquant le status de la requète + * \note si donnees != NULL, la requète sera envoyé en POST **/ int EnvoieRequete(LPCSTR donnees = 0, DWORD donnees_len = 0, DWORD debut = 0); + /** Envoie la connexion - * \param[in] donnees chaine de caractères à envoyer avec la requète - * \param[in] donnees_len longueur de donnees * \param[in] debut indique la position de lecture facultative (position pour la récupération d'un morceau) * \retval 0 en cas d'erreur * \return une valeur de HTTP_ERR indiquant le status de la requète - * \info si donnees != NULL, la requète sera envoyé en POST **/ int EnvoieRequete(DWORD debut) {this->EnvoieRequete(0, 0, debut);}; + /** Retourne le status de la connexion * \return le code status de la connexion **/ int GetStatus() {return this->m_dwStatus;}; + /** Retourne la taille du fichier * \return la taille du fichier **/ DWORD GetTaille() {return this->m_dwTaille;}; + /** Retourne le type de contenue * \param[out] content récupère le type de fichiers (ex. "text/html", "application/x-msdos-program") * \param[in,out] longueur la taille de content maximale, et retourne le nombre d'octets copiés/necessaires **/ void GetContentType(LPTSTR content, UINT *longueur); + /** Retourne le nombre d'octets déjà récupérés * \return le nombre d'octets récupérés **/ DWORD GetRestant() {return this->m_dwTaille - this->m_dwRecupere;}; + /** Retourne la date/heure de modification du fichier * \return la date de modification du fichier **/ Modifié: trunk/main.cpp =================================================================== --- trunk/main.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/main.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -443,14 +443,14 @@ int ixRecDescr = enregistrements_actuels.getRecordingDescr(ixChaineCourante); bool curChannelRecording = ixRecDescr != -1; bool bFreeRecAvailable = enregistrements_actuels.getFreeDescriptor() != -1; - bool isMpeg2 = ixChaine_ok(ixChaineCourante) && Canaux[ixChaineCourante].video_type==vst_MPEG2; + bool bCanRecordPs = ixChaine_ok(ixChaineCourante) && Canaux[ixChaineCourante].isPsRecordAvailable(); bool active; // Items d'enregistrement de la chaîne courante : ces items sont actifs // si la chaîne courante n'est pas déjà en cours d'enregistrement, et si // le nombre maximal de chaînes enregistrées n'est pas atteint. active = bFreeRecAvailable && !curChannelRecording; - set_menu_enable_state(hRecMenu, IDM_RECORD_CHANNEL_PS, active && isMpeg2); + set_menu_enable_state(hRecMenu, IDM_RECORD_CHANNEL_PS, active && bCanRecordPs); set_menu_enable_state(hRecMenu, IDM_RECORD_CHANNEL_TS, active); // Enregistrement du multiplex : cette fonctionnalité doit être activée @@ -520,10 +520,10 @@ for (int i=0; i 6) eWinVers = wv_Newer; - } + } myprintf( TEXT("Fonctionne sous ") BOLD(TEXT("Windows ") TEXT("%") A2t) EOL TEXT("[Windows version %s]") EOL, Modifié: trunk/main.h =================================================================== --- trunk/main.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/main.h 2009-11-11 16:47:47 UTC (rev 207) @@ -97,15 +97,60 @@ /** @defgroup WM_APP_codes Liste des messages locaux à l'application * @{ **/ + +/** + * Notification d'événements transmis depuis l'icône de la barre des tâches + * \param[in] wParam Voir documentation Microsoft de \p NOTIFYICONDATA::uCallbackMessage + * \param[in] lParam Voir documentation Microsoft de \p NOTIFYICONDATA::uCallbackMessage + **/ #define WM_APP_TRAYICON_MSG (WM_APP+0) + +/** + * Notification de changement dans le guide de programmation (EPG) + **/ #define WM_APP_EPG_UPDATED (WM_APP+1) + +/** + * Notification de changement dans le format du flux TS de la chaîne, détecté par le filtre PMT + **/ #define WM_APP_PMT_UPDATED (WM_APP+2) + +/** + * Reconstruction de la liste des enregistrements programmés après changement + **/ #define WM_APP_PROG_CHANGED (WM_APP+3) + +/// Obsolete #define WM_APP_SCAN_NEXT (WM_APP+4) + +/** + * Traitement des messages d'information envoyés au cours de la recherche + * \param[in] LOBYTE(wParam) Code de notification + * \param[in] wParam Autres parties : voir #ScanNotifications + * \param[in] lParam Voir #ScanNotifications +**/ #define WM_APP_SCAN_NOTIFY (WM_APP+5) + +/** + * Définition d'un raccourci clavier par saisie de la commande + * \param[in] wParam Pointeur sur le raccourci clavier défini + * (alloué en mémoire, à supprimer par \p delete après usage) + **/ #define WM_APP_HOOK_OK (WM_APP+6) + +/** + * Annulation de saisie de raccourci clavier + **/ #define WM_APP_HOOK_CANCEL (WM_APP+7) + +/** + * Notification d'événement survenant dans le graphe + **/ #define WM_APP_GRAPHNOTIFY (WM_APP+8) + +/** + * Notification de changement de taille de la vidéo + **/ #define WM_APP_VIDEOSIZE_CHG (WM_APP+9) /** @} */ // fin de WM_APP_codes Modifié: trunk/parse.cpp =================================================================== --- trunk/parse.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/parse.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -88,6 +88,10 @@ switch (stream_type) { 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 +#if TEST_RNT_RADIO + if (pid == TEST_RNT_RADIO) + continue; +#endif lpmt_e.video_pid=pid; lpmt_e.video_type = vst_MPEG2; @@ -462,9 +466,13 @@ canal.ONID, canal.TSID, canal.SID, canal.video_pid, canal.pmt_pid, canal.pcr_pid); if (canal.video_pid==0 && canal.video_type == vst_Unknown) { - //vire cette chaîne - log(TEXT(" -- Invalide : destruction") EOL); - Canaux.erase(Canaux.begin()+(i--)); + if (canal.sons.nbr > 0) { + log(TEXT(" -- Audio seul") EOL); + } else { + //vire cette chaîne + log(TEXT(" -- Invalide : destruction") EOL); + Canaux.erase(Canaux.begin()+(i--)); + } } else { TCHAR szWrk[128]; int j; @@ -861,8 +869,16 @@ canal.etat = ec_active; // plutût que 'ec_preferee' break; - default: // crypté ... + case vst_MPEG2_encrypted: + case vst_H264_encrypted: // crypté ... canal.etat = ec_inactive; + break; + + default: + if (canal.sons.nbr > 0) + canal.etat = ec_active; // radio ... + else + canal.etat = ec_inactive; } } } Ajouté: trunk/radio.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/radio.bmp ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Modifié: trunk/record.cpp =================================================================== --- trunk/record.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/record.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -422,8 +422,8 @@ const Chaine & canal = Canaux[ixChaine]; - if (canal.video_type!=vst_MPEG2) // PS en MPEG2 seulement pour le moment - return -1; + if (!canal.isPsRecordAvailable()) + return -1; // Enregistrement PS non disponible NomFichierAvecDate nom_fichier(video_dir, getProgName(pProg), canal.nom, TEXT("mpg")); UINT16 video_pid = canal.video_pid; Modifié: trunk/recprog.cpp =================================================================== --- trunk/recprog.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/recprog.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -128,6 +128,17 @@ return identifie; } +const LPCTSTR Programme::t_states[] = +{ + TEXT("Attente"), + TEXT("En cours"), + TEXT("Désactivé"), + TEXT("Interrompu"), + TEXT("Supplanté"), + TEXT("Terminé"), + TEXT("Erreur") +}; + // Constructeur : Programme::Programme() { @@ -726,17 +737,6 @@ { TCHAR buffer[64]; - static const LPCTSTR t_states[] = - { - TEXT("Attente"), - TEXT("En cours"), - TEXT("Désactivé"), - TEXT("Interrompu"), - TEXT("Supplanté"), - TEXT("Terminé"), - TEXT("Erreur") - }; - LVITEM item = { LVIF_TEXT, // mask 0, 0, 0, 0, // iItem, iSubItem, state, stateMask @@ -763,19 +763,15 @@ ListView_SetItem(hListItem, &item); item.iSubItem = 2; - _stprintf_s(buffer, _countof(buffer), TEXT("%s %i/%02i à %ih%02i"), - prog.startDoW(), prog.debut.wDay, prog.debut.wMonth, - prog.debut.wHour, prog.debut.wMinute); + prog.formate_heure_debut(buffer, _countof(buffer)); ListView_SetItem(hListItem, &item); item.iSubItem = 3; - _stprintf_s(buffer, _countof(buffer), TEXT("%ih%02i%s"), - prog.fin.wHour, prog.fin.wMinute, - prog.repetition!=0 ? TEXT("*") : TEXT("")); + prog.formate_heure_fin(buffer, _countof(buffer)); ListView_SetItem(hListItem, &item); item.iSubItem = 4; - strcpy_T(buffer, t_states[prog.etat]); + prog.formate_etat(buffer, _countof(buffer)); ListView_SetItem(hListItem, &item); } } Modifié: trunk/recprog.h =================================================================== --- trunk/recprog.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/recprog.h 2009-11-11 16:47:47 UTC (rev 207) @@ -81,6 +81,7 @@ /// Définition d'une programmation d'enregistrement class Programme : public RecordInfo { + static const LPCTSTR t_states[]; public: SYSTEMTIME debut; //!< Date & heure de début @@ -183,6 +184,34 @@ * \retval \p true si cette programmation se classe avant la programmation \p p2 dans le temps. **/ bool operator < (const Programme & p2) const; + + /** + * Formatage de l'heure de début, pour affichage + * \param[in] pszBuf Tampon recevant la chaîne formatée + * \param[in] nCount Taille du tampon + * \retval Nombre de caractères écrits dans le tampon. + **/ + UINT32 formate_heure_debut(LPTSTR pszBuf, UINT32 nCount) const { + return _stprintf_s(pszBuf, nCount, TEXT("%s %i/%02i à %ih%02i"), + startDoW(), debut.wDay, debut.wMonth, debut.wHour, debut.wMinute); } + + /** + * Formatage de l'heure de fin, pour affichage + * \param[in] pszBuf Tampon recevant la chaîne formatée + * \param[in] nCount Taille du tampon + * \retval Nombre de caractères écrits dans le tampon. + **/ + UINT32 formate_heure_fin(LPTSTR pszBuf, UINT32 nCount) const { + return _stprintf_s(pszBuf, nCount, TEXT("%ih%02i%s"), + fin.wHour, fin.wMinute, repetition!=0 ? TEXT("*") : TEXT("")); } + + /** + * Formatage de l'état de l'enregistrement + * \param[in] pszBuf Tampon recevant la chaîne formatée + * \param[in] nCount Taille du tampon + **/ + void formate_etat(LPTSTR pszBuf, UINT32 nCount) const { + _tcscpy_s(pszBuf, nCount, t_states[etat]); } }; extern std::vector Programmes; Modifié: trunk/rendering.cpp =================================================================== --- trunk/rendering.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/rendering.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -822,6 +822,10 @@ CVideoMixingRenderer7_renderless() : CVideoMixingRenderer7() {} + + /// Obtenir le type de VMR courant + virtual VMRTypes GetVmrType() const { + return vmt_VMR7_renderless;} }; // ==================================================================================== @@ -837,6 +841,10 @@ CVideoMixingRenderer7_windowless() : CVideoMixingRenderer7() {} + + /// Obtenir le type de VMR courant + virtual VMRTypes GetVmrType() const { + return vmt_VMR7_windowless;} }; // ==================================================================================== @@ -892,6 +900,10 @@ CVideoRendererWithBitmapOSD(TEXT("Video Mixing Renderer 9"), CLSID_VideoMixingRenderer9) { } + + /// Obtenir le type de VMR courant + virtual VMRTypes GetVmrType() const { + return vmt_VMR9_windowless;} }; // ==================================================================================== @@ -945,6 +957,10 @@ CVideoRendererWithBitmapOSD(TEXT("Enhanced Video Renderer"), CLSID_EnhancedVideoRenderer) { } + + /// Obtenir le type de VMR courant + virtual VMRTypes GetVmrType() const { + return vmt_EVR;} }; // ==================================================================================== @@ -1777,10 +1793,54 @@ } /** + * Création et initialisation d'un rendu vidéo + * \param[in] eVmrMode Type de rendu vidéo à créer + * \return Code d'erreur DirectShow + **/ +HRESULT create_and_init_rendering(VMRTypes eVmrMode) +{ + // Détruire le rendu vidéo précédent s'il en existait un + if (pVMR) { + delete pVMR; + pVMR = NULL; + } + + switch (eVmrMode) { + + case vmt_null: + pVMR = new CNullVideoRenderer(); + break; + + case vmt_VMR7_windowless: + pVMR = new CVideoMixingRenderer7_windowless(); + break; + + case vmt_VMR7_renderless: + pVMR = new CVideoMixingRenderer7_renderless(); + break; + + case vmt_VMR9_windowless: + pVMR = new CVideoMixingRenderer9(); + break; + + case vmt_EVR: + pVMR = new CEnhancedVideoRenderer(); + + default: + return E_FAIL; + } + + if (!pVMR) + return E_OUTOFMEMORY; + return pVMR->Init(); +} + +/** * Initialisation du Video Mixing Renderer - * \return Code d'erreur DirectShow + * \param[in] bNoRendering Si \p true, le pseudo rendu vidéo sera substitué + * \return Code d'erreur DirectShow **/ -HRESULT init_vmr() +HRESULT init_vmr(bool bNoRendering) { if (!pGraph) return E_FAIL; @@ -1797,42 +1857,16 @@ if (bRunning) hr = pGraph->graph_Stop(); - switch (vmr_mode) { + hr = create_and_init_rendering(bNoRendering ? vmt_null : vmr_mode); - case vmt_null: - pVMR = new CNullVideoRenderer(); - break; - - case vmt_VMR7_windowless: - pVMR = new CVideoMixingRenderer7_windowless(); - break; - - case vmt_VMR7_renderless: - pVMR = new CVideoMixingRenderer7_renderless(); - break; - - case vmt_VMR9_windowless: - pVMR = new CVideoMixingRenderer9(); - break; - - case vmt_EVR: - pVMR = new CEnhancedVideoRenderer(); + if (SUCCEEDED(hr)) { + if (SUCCEEDED(hr) && bRunning) + hr = pGraph->graph_Run(); + } else { + // Échec de l'initialisation du VMR + myprintf(TEXT("Échec de l'initialisation du rendu vidéo") EOL); + clean_vmr(); } - - if (pVMR) { - hr = pVMR->Init(); - - if (SUCCEEDED(hr)) { - if (SUCCEEDED(hr) && bRunning) - hr = pGraph->graph_Run(); - } else { - // Échec de l'initialisation du VMR - myprintf(TEXT("Échec de l'initialisation du rendu vidéo") EOL); - delete pVMR; - pVMR = NULL; - } - } else - hr = E_OUTOFMEMORY; } return hr; @@ -1857,10 +1891,10 @@ /** * Débranchement du codec connecté au VMR, et branchement d'un nouveau - * \param[in] sDData Nouveau codec à insérer + * \param[in] pDData Pointeur sur nouveau codec à insérer, ou NULL si aucun * \return Code d'erreur DirectShow **/ -HRESULT switch_codec(DecoderData & sDData) +HRESULT switch_codec(DecoderData * pDData) { if (!pGraph) return E_FAIL; @@ -1874,10 +1908,21 @@ return erreur(TEXT("Arrêt du graphe impossible"), hr); if (FAILED(hr = pVMR->Disconnect())) return erreur(TEXT("Erreur lors du retrait du codec vidéo précédent"), hr); - if (sDData.pFilter) { // Si le codec existe, bien sûr - if (FAILED(hr = pVMR->Connect(sDData.pFilter))) - return erreur(TEXT("Erreur lors de l'ajout du codec %") A2t, hr, sDData.pszType); + + if (pDData && pDData->pFilter) { // Si le codec existe, bien sûr + if (pVMR->GetVmrType()!=vmr_mode) { + if (FAILED(hr = create_and_init_rendering(vmr_mode))) + return erreur(TEXT("Erreur lors de la restauration du rendu vidéo"), hr); + } + if (FAILED(hr = pVMR->Connect(pDData->pFilter))) + return erreur(TEXT("Erreur lors de l'ajout du codec %") A2t, hr, pDData->pszType); + } else { + if (pVMR->GetVmrType()!=vmt_null) { + if (FAILED(hr = create_and_init_rendering(vmt_null))) + return erreur(TEXT("Erreur lors de la création du pseudo rendu vidéo"), hr); + } } + if (bRunning && (hr = pGraph->graph_Run())!=S_OK) return erreur(TEXT("Redémarrage du graphe impossible"), hr); } Modifié: trunk/rendering.h =================================================================== --- trunk/rendering.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/rendering.h 2009-11-11 16:47:47 UTC (rev 207) @@ -134,6 +134,10 @@ myprintf(TEXT("Construction du rendu vidéo (%s)") EOL, pszName); } + /// Obtenir le type de VMR courant + virtual VMRTypes GetVmrType() const { + return vmt_null;} + /// Signifier au VMR que le mode d'affichage a changé virtual HRESULT DisplayModeChanged() { return S_OK;} @@ -507,16 +511,17 @@ /** * Initialisation du Video Mixing Renderer - * \return Code d'erreur DirectShow + * \param[in] bNoRendering Si \p true, le pseudo rendu vidéo sera substitué + * \return Code d'erreur DirectShow **/ -HRESULT init_vmr(); +HRESULT init_vmr(bool bNoRendering); /** * Débranchement du codec connecté au VMR, et branchement d'un nouveau - * \param[in] sDData Nouveau codec à insérer + * \param[in] pDData Pointeur sur nouveau codec à insérer, ou NULL si aucun * \return Code d'erreur DirectShow **/ -HRESULT switch_codec(DecoderData & sDData); +HRESULT switch_codec(DecoderData * pDData); /** * Nettoyage du VMR et de l'OSD Modifié: trunk/res.rc =================================================================== --- trunk/res.rc 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/res.rc 2009-11-11 16:47:47 UTC (rev 207) @@ -659,6 +659,8 @@ // IDB_BITMAP BITMAP "prog.bmp" +IDB_TV_GENERIC BITMAP "tv.bmp" +IDB_RADIO_GENERIC BITMAP "radio.bmp" ///////////////////////////////////////////////////////////////////////////// // Modifié: trunk/resource.h =================================================================== --- trunk/resource.h 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/resource.h 2009-11-11 16:47:47 UTC (rev 207) @@ -6,6 +6,8 @@ #define IDI_PROG_ICON 101 #define IDI_ICON_REC 102 #define IDB_BITMAP 105 +#define IDB_TV_GENERIC 106 +#define IDB_RADIO_GENERIC 107 #define IDR_MAIN_MENU 110 #define IDR_AUTHORS 112 #define IDR_CANAUX 114 @@ -219,6 +221,7 @@ #define IDM_DEFAULT_ZOOM 40054 #define IDM_ALLWDT 40055 #define IDM_ALLHGT 40056 +#define IDM_LAST_CHAN 40059 #define IDM_CHAN_AUG 40060 #define IDM_CHAN_DIM 40061 #define IDM_CHAN_AUG_MPX 40062 Ajouté: trunk/tv.bmp =================================================================== (les fichiers binaires diffèrent) Property changes on: trunk/tv.bmp ___________________________________________________________________ Ajouté : svn:mime-type + application/octet-stream Modifié: trunk/utils.cpp =================================================================== --- trunk/utils.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/utils.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -524,25 +524,27 @@ * Convertir une chaine de caractères en UTF-8 * * \param[in] aconvertir chaîne de caractères contenant éventuellement des caractères devant être encodés en UTF-8 + * \param[in] for_sgml si \p true, les caractères <, > et & sont convertis en entités SGML * \return chaîne de caractères convertie **/ -std::string ConvertChar2UTF8(LPCSTR aconvertir) +std::string ConvertChar2UTF8(LPCSTR aconvertir, bool for_sgml) { if (!aconvertir) return ""; COPY_STR_ON_STACK(WCHAR, temp, aconvertir, taille); - return ConvertChar2UTF8(temp); + return ConvertChar2UTF8(temp, for_sgml); } /** * Convertir une chaine de caractères en UTF-8 * * \param[in] aconvertir chaîne de caractères contenant éventuellement des caractères devant être encodés en UTF-8 + * \param[in] for_sgml si \p true, les caractères <, > et & sont convertis en entités SGML * \return chaîne de caractères convertie **/ -std::string ConvertChar2UTF8(LPCWSTR aconvertir) +std::string ConvertChar2UTF8(LPCWSTR aconvertir, bool for_sgml) { LPSTR pszTmp = ""; @@ -557,11 +559,11 @@ UINT taille = strlen_T(aconvertir); // Allouer l'espace - pszTmp = STK_ALLOC(CHAR, taille*4+1); // Chaîne de carastères temporaire (la taille max de la - // chaîne est de 4 octets par caractère original) + pszTmp = STK_ALLOC(CHAR, taille*5+1); // Chaîne de carastères temporaire (la taille max de la + // chaîne est de 5 octets par caractère original) // Effectuer la conversion for(i=0, j=0; i et & sont convertis en entités SGML * \return le nombre de caractères convertis * \note \p aconvertir est de type \p UINT32 car : * - TCHAR pose des problèmes étant donné qu'il s'agit d'une valeur *signée* * - La fonction est capable de convertir des caractères codés sur plus de 16 bits * \note \p convertis doit pointer sur une variable de taille suffisante - * pour être capable de recevoir au moins 5 caractères (terminateur compris). + * pour être capable de recevoir au moins 6 caractères (terminateur compris). **/ -int ConvertChar2UTF8(UINT32 aconvertir, LPSTR convertis) +int ConvertChar2UTF8(UINT32 aconvertir, LPSTR convertis, bool for_sgml) { int j; // Itérateur @@ -593,6 +596,18 @@ if (aconvertir <= 0x7F) { convertis[0] = (char)aconvertir; j = 1; + if (for_sgml) { + LPCSTR sgml = NULL; + switch (aconvertir) { + case '&': sgml = "&"; break; + case '<': sgml = "<"; break; + case '>': sgml = ">"; + } + if (sgml) { + strcpy_s(convertis, 6, sgml); + j = (int)strlen(sgml); + } + } } else if (aconvertir <= 0x7FF) { convertis[0] = (char)(0xC0 | ((aconvertir>>6) & 0x1F)); convertis[1] = (char)(0x80 | (aconvertir & 0x3F)); @@ -646,8 +661,50 @@ return RTrimStr(szBuffer); // Conversion implicite en tstring } -// ---------------------------------------------------------------------------- +// ==================================================================================== +// Ressources +// ==================================================================================== +/** + * Extrait une resource du fichier. Charge également la taille allouée. + * \param[in] hInstance Instance de l'application. + * \param[in] idRessource Identifiant de la resource. + * \param[in] lpType Type de la resource. + * \retval \p true en cas de succès, \p false en cas d'échec. + **/ +bool RawResource::Extraction(HINSTANCE hInstance, UINT idRessource, LPCTSTR lpType) +{ + HRSRC hRcdataResource = FindResource(hInstance, MAKEINTRESOURCE(idRessource), lpType); + bool bRes = false; + + if (hRcdataResource != NULL) { + taille = SizeofResource(hInstance, hRcdataResource); + // Charge la ressource identifiée + HGLOBAL hRcdataCharge = LoadResource(hInstance, hRcdataResource); + + if (hRcdataCharge != NULL) { + // Bloque la ressource en mémoire pour utilisation + LPBYTE RcdataRes = (LPBYTE)LockResource(hRcdataCharge); + + if (RcdataRes != NULL) { + // Tout s'est bien passé: on peut utiliser la resource + contenu = new BYTE[taille + 1]; + ZeroMemory(contenu, taille + 1); + for (int i=0; i et & sont convertis en entités SGML * \return chaîne de caractères convertie **/ -std::string ConvertChar2UTF8(LPCWSTR aconvertir); +std::string ConvertChar2UTF8(LPCWSTR aconvertir, bool for_sgml=false); /** * Convertir une chaine de caractères en UTF-8 * * \param[in] aconvertir chaîne de caractères contenant éventuellement des caractères devant être encodés en UTF-8 + * \param[in] for_sgml si \p true, les caractères <, > et & sont convertis en entités SGML * \return chaîne de caractères convertie **/ -std::string ConvertChar2UTF8(LPCSTR aconvertir); +std::string ConvertChar2UTF8(LPCSTR aconvertir, bool for_sgml=false); /** * Convertir un caractère en UTF-8 * * \param[in] aconvertir chaîne de caractères contenant éventuellement des caractères devant être encodés en UTF-8 * \param[out] convertis chaîne de caractères convertie + * \param[in] for_sgml si \p true, les caractères <, > et & sont convertis en entités SGML * \return le nombre de caractères convertis * \note \p aconvertir est de type \p UINT32 car : * - TCHAR pose des problèmes étant donné qu'il s'agit d'une valeur *signée* * - La fonction est capable de convertir des caractères codés sur plus de 16 bits * \note \p convertis doit pointer sur une variable de taille suffisante - * pour être capable de recevoir au moins 5 caractères (terminateur compris). + * pour être capable de recevoir au moins 6 caractères (terminateur compris). **/ -int ConvertChar2UTF8(UINT32 aconvertir, LPSTR convertis); +int ConvertChar2UTF8(UINT32 aconvertir, LPSTR convertis, bool for_sgml=false); // ---------------------------------------------------------------------------- @@ -837,6 +840,38 @@ // ---------------------------------------------------------------------------- +/// Classe permettant de récupérer les fichiers inclus dans les resources de PTVM +class RawResource +{ +public: + int taille; ///< taille de la ressource concernée + LPBYTE contenu; ///< contenu de la ressource + + RawResource() : + taille(0), + contenu(NULL) + {} + + /** + * Extrait une resource du fichier. Charge également la taille allouée. + * \param[in] hInstance Instance de l'application. + * \param[in] idRessource Identifiant de la resource. + * \param[in] lpType Type de la resource. + * \retval \p true en cas de succès, \p false en cas d'échec. + **/ + bool Extraction(HINSTANCE hInstance, UINT idRessource, LPCTSTR lpType=RT_RCDATA); + + operator LPCSTR() const { + return reinterpret_cast(contenu);} + + ~RawResource() { + if (contenu) + delete [] contenu; + } +}; + +// ---------------------------------------------------------------------------- + class WorkingThread { HANDLE hThread; Modifié: trunk/xml.cpp =================================================================== --- trunk/xml.cpp 2009-11-10 10:32:33 UTC (rev 206) +++ trunk/xml.cpp 2009-11-11 16:47:47 UTC (rev 207) @@ -549,25 +549,11 @@ **/ int CXMLOutput::put(LPCSTR name, LPCWSTR str) { - UINT ch; std::string buff = ConvertChar2UTF8(name); add_indent(); add_open(buff.c_str()); - while ((ch = *str++)!=0) { - CHAR bufch[8]; - - switch (ch) { - - case '&': add("&"); break; - case '<': add("<"); break; - case '>': add(">"); break; - - default: - ConvertChar2UTF8(ch, bufch); - add(bufch); - } - } + add(ConvertChar2UTF8(str, true).c_str()); add_close(buff.c_str()); return send(); } From pouchintv-dev at baysse.fr Wed Nov 11 18:50:32 2009 From: pouchintv-dev at baysse.fr (=?iso-8859-1?q?Liste_utilis=E9e_par_les_d=E9veloppeurs?=) Date: mer, 11 nov 2009 18:50:32 +0100 Subject: [Pouchintv-dev] [PouchinTVMod] gingko | r208 - trunk Message-ID: <20091111175032.E5EC15F75B@mail.baysse.fr> Author: gingko Date: 2009-11-11 18:50:32 +0100 (mer 11 nov 2009) New Revision: 208 Modified: trunk/changelog.html trunk/rendering.cpp Log: Petite erreur : le rendu EVR ne fonctionnait plus avec la dernière livraison (0.5.207). Modifié: trunk/changelog.html =================================================================== --- trunk/changelog.html 2009-11-11 16:47:47 UTC (rev 207) +++ trunk/changelog.html 2009-11-11 17:50:32 UTC (rev 208) @@ -56,7 +56,7 @@

    Changements réalisés pour la version 0.5

    -
    0.5.207 (expérimentale, publiée dans le forum le 11 novembre 2009) :
    +
    0.5.208 (expérimentale, publiée dans le forum le 11 novembre 2009) :
    • Ajout de la prise en charge des radios numériques DVB telles que celles qu'on peut avoir en Belgique.
    • Ajout d'un raccourci clavier (backspace par défaut) permettant de revenir sur la chaîne précédemment Modifié: trunk/rendering.cpp =================================================================== --- trunk/rendering.cpp 2009-11-11 16:47:47 UTC (rev 207) +++ trunk/rendering.cpp 2009-11-11 17:50:32 UTC (rev 208) @@ -1825,6 +1825,7 @@ case vmt_EVR: pVMR = new CEnhancedVideoRenderer(); + break; default: return E_FAIL;