Strona główna

Program TV

Program telewizyjny z powiadamiaczem. 


Pisanie nowych wtyczek źródeł pobierania w wersji 4

Zadaniem wtyczek źródeł pobierania jest dostarczenie programu telewizyjnego do aplikacji. Polega to na tym, że aplikacja wysyła do wtyczki żądanie pobrania programu telewizyjnego dla określonego kanału i dnia, a następnie wtyczka pobiera kod źródłowy strony internetowej zawierający dany program telewizyjny, z którego to wyciąga potrzebne informacje, poddaje je dodatkowej obróbce i zwraca je do aplikacji.

Wtyczki źródeł pobierania są to biblioteki dll, które znajdują się w podfolderze Źródła w katalogu głównym aplikacji Program TV. Nazwy tych plików składają się z adresu internetowego (z którego pobierany jest program telewizyjny bez przedrostka typu http:// i katalogów podrzędnych, oraz wszystkie kropki zamienia się na podkreślenia) i rozrzerzenia dll. Biblioteki te muszą udostępniać trzy funkcje: Kanaly, Pobierz i Odebrane. Dodatkowo biblioteki mogą również opcjonalnie udostępniać sześć funkcji: OdebraneOpisy, OdebraneKategorie, OdebraneHity, OdebraneObrazki, Opcje i Logo.


Listy kanałów

Dla wtyczek pobierających program telewizyjny ze stron internetowych oferujących program telewizyjny dla dużej liczby kanałów może istnieć dodatkowy plik znajdujący się obok pliku wtyczki, o takiej samej nazwie ale z rozszerzeniem txt. Plik ten zawiera listę kanałów, co umożliwia dodanie nowych kanałów, które dana wtyczka może obsługiwać, bez konieczności pisania nowej wtyczki.

Wpisy kanałów, w pliku listy kanałów, zaczynają się od czwartego wiersza i zbudowane są z nazw kanałów i adresów internetowych pod którymi znajduje się program telewizyjny dla danego kanału, połączonych znakiem równości w postaci:

Kanał = Adres

Ponieważ nazwy kanałów wykorzystywane są przez aplikację do tworzenia folderów, to nazwy te nie mogą zawierać znaków specjalnych zastrzeżonych przez system Windows.

Pierwszy i trzeci wiersz, w pliku listy kanałów, to komentarze, natomiast drugi wiersz to numer wersji listy kanałów i jest on w postaci:

Wersja:   x

gdzie x to numer wersji listy kanałów.


Funkcje udostępniane przez wtyczki

Każda wtyczka musi udostępniać aplikacji następujące funkcje:

Dodatkowo wtyczka może udostępniać aplikacji następujące funkcje:


Przykładowy szkielet wtyczki obsługującej wszystkie funkcje napisany w C++ Builder 6 dla fikcyjnej strony internetowej www.informacje.pl/programtv

Zgodnie z tym co napisano na wstępie dla fikcyjnej strony "www.informacje.pl/programtv" plik wtyczki powinien się nazywać "www_informacje_pl.dll" a plik listy kanałów (jeśli ma być obsługiwany) "www_informacje_pl.txt".

Wtyczka taka powinna się składać z co najmniej jednego pliku nagłówkowego ".h" i jednego pliku źródłowego ".cpp", przeznaczonych dla funkcji wtyczki (nazwijmy je przykładowo Kod.h i Kod.cpp). Opcionalnie jeśli wtyczka ma zawierać formularz ustawień to powinny istnieć jeszcze dwa takie pliki (nazwijmy je przykładowo Ustawienia.h i Ustawienia.cpp).

Poniżej zostaną przedstawione zawartości tych plików z zaznaczonymi miejscami, które należy odpowiednio zmodyfikować.


Zawartość pliku nagłówkowego Kod.h:

//---------------------------------------------------------------------------

#ifndef KodH
#define KodH
//---------------------------------------------------------------------------

extern "C" __declspec(dllexport) char* __stdcall Kanaly(int Nr=-1);
extern "C" __declspec(dllexport) int __stdcall Pobierz(char *Kanal,TDateTime Data,
                                                                         bool Dekoduj=true);
extern "C" __declspec(dllexport) char* __stdcall Odebrane(int Nr=-1);
extern "C" __declspec(dllexport) char* __stdcall OdebraneOpisy(int Nr);
extern "C" __declspec(dllexport) char* __stdcall OdebraneKategorie(int Nr);
extern "C" __declspec(dllexport) char* __stdcall OdebraneHity(int Nr);
extern "C" __declspec(dllexport) char* __stdcall OdebraneObrazki(int Nr);
extern "C" __declspec(dllexport) bool __stdcall Opcje(TApplication *Host);
extern "C" __declspec(dllexport) bool __stdcall Logo(char *Kanal);
//---------------------------------------------------------------------------

#endif

Zawartość pliku źródłowego Kod.cpp:

//---------------------------------------------------------------------------

#include <vcl.h>
#include <windows.h>
#include <urlmon.h>
#pragma hdrstop
#include "Kod.h"
#include "Ustawienia.h"
#pragma argsused
//---------------------------------------------------------------------------

TStringList *Stacje=NULL;
TStringList *Lista=NULL;
TStringList *ListaKategori=NULL;
TStringList *ListaOpisow=NULL;
TStringList *ListaObrazkow=NULL;
TStringList *ListaHitow=NULL;
char *DaneKanalu=NULL;
char *DaneOdebrane=NULL;
char *DaneOdebraneKategorie=NULL;
char *DaneOdebraneOpisy=NULL;
char *DaneOdebraneObrazki=NULL;
char *DaneOdebraneHity=NULL;
//---------------------------------------------------------------------------

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
    if(reason==DLL_PROCESS_DETACH)
        {
        if(DaneKanalu)
            {
            delete[] DaneKanalu;
            DaneKanalu=NULL;
            }
        if(DaneOdebrane)
            {
            delete[] DaneOdebrane;
            DaneOdebrane=NULL;
            }
        if(DaneOdebraneKategorie)
            {
            delete[] DaneOdebraneKategorie;
            DaneOdebraneKategorie=NULL;
            }
        if(DaneOdebraneOpisy)
            {
            delete[] DaneOdebraneOpisy;
            DaneOdebraneOpisy=NULL;
            }
        if(DaneOdebraneObrazki)
            {
            delete[] DaneOdebraneObrazki;
            DaneOdebraneObrazki=NULL;
            }
        if(DaneOdebraneHity)
            {
            delete[] DaneOdebraneHity;
            DaneOdebraneHity=NULL;
            }
        if(Stacje)
            {
            delete Stacje;
            Stacje=NULL;
            }
        if(Lista)
            {
            delete Lista;
            Lista=NULL;
            }
        if(ListaKategori)
            {
            delete ListaKategori;
            ListaKategori=NULL;
            }
        if(ListaOpisow)
            {
            delete ListaOpisow;
            ListaOpisow=NULL;
            }
        if(ListaObrazkow)
            {
            delete ListaObrazkow;
            ListaObrazkow=NULL;
            }
        if(ListaHitow)
            {
            delete ListaHitow;
            ListaHitow=NULL;
            }
        }
    return 1;
    }
//---------------------------------------------------------------------------

char* __stdcall Kanaly(int Nr)
    {
    if(DaneKanalu)
        {
        delete[] DaneKanalu;
        DaneKanalu=NULL;
        }
    if(!Stacje)
        {
        Stacje=new TStringList;
        if(FileExists("Źródła\\www_informacje_pl.txt"))     // Odczyt listy kanałów jeśli
            {                                               // wtyczka ją obsługuje.
            Stacje->LoadFromFile("Źródła\\www_informacje_pl.txt");
            Stacje->Delete(2);
            Stacje->Delete(1);
            Stacje->Delete(0);
            }
        }
    String Dane;
    if(Nr<-1) Dane="Nazwa kanału=Adres internetowy kanału"; // Przykładowy kanał i adres dla
    if(Nr==-1) Dane=IntToStr(Stacje->Count);                // edytora, a przy braku obsługi
    if(Nr>-1) Dane=Stacje->Names[Nr];                       // listy kanałów zmienną ustawia
    DaneKanalu=new char[Dane.Length()+1];                   // się pustą (Dane="").
    strcpy(DaneKanalu,Dane.c_str());
    return DaneKanalu;
    }
//---------------------------------------------------------------------------

int __stdcall Pobierz(char *Kanal,TDateTime Data,bool Dekoduj)
    {
    int Status=1;
    Kanaly();
    AnsiString Adres="";
    Adres=Stacje->Values[Kanal];
    if(Adres=="")
        {
        Status=2;
        }
    else
        {
        Adres=Adres; // Dostosowanie adresu z listy kanałów do rzeczywistego.
        AnsiString Plik="Pobrane\\"+String(Kanal)+"\\"+Data+".html";
        int Stan=URLDownloadToFile(0,Adres.c_str(),Plik.c_str(),0,0);
        if(Dekoduj==true)
            {
            if((Stan==S_OK)&&(FileExists(Plik)))
                {
                if(Lista)
                    {
                    Lista->Clear();
                    }
                else
                    {
                    Lista=new TStringList;
                    }
                if(ListaKategori)
                    {
                    ListaKategori->Clear();
                    }
                else
                    {
                    ListaKategori=new TStringList;
                    }
                if(ListaOpisow)
                    {
                    ListaOpisow->Clear();
                    }
                else
                    {
                    ListaOpisow=new TStringList;
                    }
                if(ListaObrazkow)
                    {
                    ListaObrazkow->Clear();
                    }
                else
                    {
                    ListaObrazkow=new TStringList;
                    }
                if(ListaHitow)
                    {
                    ListaHitow->Clear();
                    }
                else
                    {
                    ListaHitow=new TStringList;
                    }
                TStringList *Html=new TStringList;
                for(;;)
                    {
                    try
                        {
                        Html->LoadFromFile(Plik);
                        break;
                        }
                    catch(...)
                        {
                        Sleep(1000);
                        }
                    }
                String Szukane="tekst wskazujący na obecność programu telewizyjnego";
                for(int i=0;i<Html->Count;i++)
                    {
                    String Dane=Html->Strings[i];
                    if(Dane.Pos(Szukane)>0)
                        {
                        Status=0;
                        /*
             Wydobycje poszczególnych danych dla każdej pozycji z ramówki      
             programu telewizyjnego i ich zapis do odpowiednich list:          
               - dla listy "Lista" zapis rzeczywistej daty emisji, godziny     
                 emisji i tytułu pozycji w postaci "yyyy-mm-dd hh:nn Tytuł",   
               - dla listy "ListaOpisow" zapis opisu dla danej pozycji a przy  
                 braku zapis pustej wartości,                                  
               - dla listy "ListaKategori" zapis kategorii a przy braku zapis  
                 pustej wartości,                                              
               - dla listy "ListaHitow" zapis stanu czy dana pozycja jest      
                 hitem (0 - nie lub 1 - tak),                                  
               - dla listy "ListaObrazkow" zapis adresu obrazka a przy braku   
                 zapis pustej wartości.                                        
             Uwaga! Listy: "ListaOpisow", "ListaKategori", "ListaHitow" i      
             "ListaObrazkow" są listami opcionalnymi, które występują tylko    
             wtedy, gdy wtyczka obsługuje dane funkcje i muszą być połączone z 
             listą główną "Lista" relacją jeden do jeden za pomocą numerów     
             indeksów list.                                                    
                        */
                        break;
                        }
                    }
                delete Html;
                }
            }
        else
            {
            if((Stan==S_OK)&&(FileExists(Plik))) Status=0;
            }
        }
    return Status;
    }
//---------------------------------------------------------------------------

char* __stdcall Odebrane(int Nr)
    {
    if(DaneOdebrane)
        {
        delete[] DaneOdebrane;
        DaneOdebrane=NULL;
        }
    String Dane;
    if(Nr==-1) Dane=IntToStr(Lista->Count);
    if(Nr>-1) Dane=Lista->Strings[Nr];
    DaneOdebrane=new char[Dane.Length()+1];
    strcpy(DaneOdebrane,Dane.c_str());
    return DaneOdebrane;
    }
//---------------------------------------------------------------------------

char* __stdcall OdebraneKategorie(int Nr)
    {
    if(DaneOdebraneKategorie)
        {
        delete[] DaneOdebraneKategorie;
        DaneOdebraneKategorie=NULL;
        }
    String Dane;
    Dane=ListaKategori->Strings[Nr];
    DaneOdebraneKategorie=new char[Dane.Length()+1];
    strcpy(DaneOdebraneKategorie,Dane.c_str());
    return DaneOdebraneKategorie;
    }
//---------------------------------------------------------------------------

char* __stdcall OdebraneOpisy(int Nr)
    {
    if(DaneOdebraneOpisy)
        {
        delete[] DaneOdebraneOpisy;
        DaneOdebraneOpisy=NULL;
        }
    String Dane;
    Dane=ListaOpisow->Strings[Nr];
    DaneOdebraneOpisy=new char[Dane.Length()+1];
    strcpy(DaneOdebraneOpisy,Dane.c_str());
    return DaneOdebraneOpisy;
    }
//---------------------------------------------------------------------------

char* __stdcall OdebraneObrazki(int Nr)
    {
    if(DaneOdebraneObrazki)
        {
        delete[] DaneOdebraneObrazki;
        DaneOdebraneObrazki=NULL;
        }
    String Dane;
    Dane=ListaObrazkow->Strings[Nr];
    DaneOdebraneObrazki=new char[Dane.Length()+1];
    strcpy(DaneOdebraneObrazki,Dane.c_str());
    return DaneOdebraneObrazki;
    }
//---------------------------------------------------------------------------

char* __stdcall OdebraneHity(int Nr)
    {
    if(DaneOdebraneHity)
        {
        delete[] DaneOdebraneHity;
        DaneOdebraneHity=NULL;
        }
    String Dane;
    Dane=ListaHitow->Strings[Nr];
    DaneOdebraneHity=new char[Dane.Length()+1];
    strcpy(DaneOdebraneHity,Dane.c_str());
    return DaneOdebraneHity;
    }
//---------------------------------------------------------------------------

bool __stdcall Opcje(TApplication *Host)
    {
    TApplication *Dll=Application;
    Application=Host;
    TFormOpcje *Formularz=new TFormOpcje(Application);
    Formularz->ShowModal();
    delete Formularz;
    Application=Dll;
    return ::Edytor;           // Gdy zwraca true to po zamknięciu okna ustawień wtyczki
    }                          // zostanie wyświetlony edytor listy kanałów.
//---------------------------------------------------------------------------

bool __stdcall Logo(char *Kanal)
    {
    bool Stan=false;
    String Data=DateToStr(Date());
    if(!FileExists("Pobrane\\"+String(Kanal)+"\\"+Data+".html")) Pobierz(Kanal,
                                                                     StrToDate(Data),false);
    if(FileExists("Pobrane\\"+String(Kanal)+"\\"+Data+".html"))
        {
        TStringList *Html=new TStringList;
        for(;;)
            {
            try
                {
                Html->LoadFromFile("Pobrane\\"+String(Kanal)+"\\"+Data+".html");
                break;
                }
            catch(...)
                {
                Sleep(1000);
                }
            }
        String Szukane="tekst wskazujący na adres loga kanału";
        for(int i=0;i<Html->Count;i++)
            {
            String Dane=Html->Strings[i];
            if(Dane.Pos(Szukane)>0)
                {
                Dane=Dane; // Przypisanie wyciętego adresu loga kanału.
                int Status=URLDownloadToFile(0,Dane.c_str(),("Ustawienia\\"+String(Kanal)+
                                                         "\\Logo.png lub jpg").c_str(),0,0);
                if((Status==S_OK)&&(FileExists("Ustawienia\\"+String(Kanal)+
                                                          "\\Logo.png lub jpg"))) Stan=true;
                break;
                }
            }
        delete Html;
        }
    return Stan;
    }
//---------------------------------------------------------------------------

Zawartość pliku nagłówkowego Ustawienia.h:

//---------------------------------------------------------------------------

#ifndef UstawieniaH
#define UstawieniaH
//---------------------------------------------------------------------------

#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------

class TFormOpcje : public TForm
{
__published: // IDE-managed Components
private:     // User declarations
public:	     // User declarations
        __fastcall TFormOpcje(TComponent* Owner);
};
//---------------------------------------------------------------------------

extern PACKAGE TFormOpcje *FormOpcje;
extern bool Edytor;
//---------------------------------------------------------------------------

#endif

Zawartość pliku źródłowego Ustawienia.cpp:

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include "Ustawienia.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------

TFormOpcje *FormOpcje;
bool Edytor=false;
//---------------------------------------------------------------------------

__fastcall TFormOpcje::TFormOpcje(TComponent* Owner)
        : TForm(Owner)
    {

    }
//---------------------------------------------------------------------------

Stronę tę odwiedziło 2000 użytkowników.
Całkowita liczba odwiedzin serwisu to 5591 użytkowników i 34706 robotów.