Program telewizyjny z powiadamiaczem.
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ć siedem funkcji: OdebraneOpisy, OdebraneKategorie, OdebraneHity, OdebraneObrazki, Opcje, PobierzLogo i PobierzPlik.
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.
Funkcja ta może zwrócić trzy rodzaje informacji jako tablicę char, w zależności od podanej wartości parametru Nr: | ||
dla Nr = -1 | - | funkcja zwraca liczbę obsługiwanych przez wtyczkę kanałów (domyślnie), |
dla Nr > -1 | - | funkcja zwraca nazwy poszczególnych kanałów, |
dla Nr < -1 | - | funkcja zwraca pustą tablicę jeśli wtyczka nie obsługuje listy kanałów lub gdy ją obsługuje to zwraca przykładowy wpis listy kanałów składający się z nazwy kanału połączonego znakiem równości z adresem internetowym pod którym można pobrać program telewizyjny dla podanego kanału. |
Funkcja ta pobiera kod źródłowy strony internetowej zawierającej program telewizyjny do odpowiedniego pliku html, którego nazwa składa się z daty w formacje yyyy-mm-dd (rok-miesiąc-dzień) i rozszerzenia html. Plik ten zapisywany jest do odpowiedniego podfolderu, którym jest nazwa kanału w katalogu głównym aplikacji w folderze Pobrane.
Jeśli zmienna globalna ::Dekoduj ustawiona jest na true (domyślnie), to funkcja ta wydobywa z pobranego pliku wszystkie niezbędne dane na temat programu telewizyjnego i zapisuje je do odpowiednich list globalnych zdefiniowanych we wtyczce, przy czym liczba pozycji we wszystkich listach musi być zgodna, więc jeżeli jakaś dana nie występuje to do danej listy należy dodać pustą wartość, ponieważ aplikacja później będzie łączyć te dane ze wszystkich list w całość odwołując się do nich po numerach indeksów.
Funkcja ta może też być wykorzystywana wewnętrznie przez funkcję PobierzLogo w celu pobrania źródła strony internetowej dla odpowiedniego kanału. Jednak wtedy, przed wywołaniem tej funkcji zostanie ustawiona zmienna globalna ::Dekoduj na false, a funkcja ta ma tylko pobrać odpowiedni plik i nic więcej z nim nie robić tylko zakończyć swoje działanie, przy czym wcześniej z powrotem musi przywrócić wartość zmiennej globalnej ::Dekoduj na true.
Funkcja ta nie zwraca do aplikacji żadnych danych na temat programu telewizyjnego, a jedynie status z przeprowadzonej operacji. Wyniki działania tej funkcji aplikacja odbiera za pomocą funkcji Odebrane oraz funkcji opcjonalnych: OdebraneOpisy, OdebraneKategorie, OdebraneHity i OdebraneObrazki.
Parametry wejściowe to: | ||
char *Kanal | - | nazwa kanału dla którego ma być pobrany program telewizyjny. |
TDateTime Data | - | dzień dla którego ma być pobrany program telewizyjny (format: yyyy-mm-dd). |
Funkcja zwraca wartość typu int: | ||
0 | - | gdy operacja zakończyła się sukcesem. |
1 | - | gdy wystąpił błąd. |
2 | - | gdy brak jest listy kanałów lub kanału w liście kanałów. |
Funkcja ta zwraca do aplikacji wyniki z wcześniej uruchomionej funkcji Pobierz.
Funkcja ta może zwrócić dwa rodzaje informacji jako tablicę char, w zależności od podanej wartości parametru Nr: | |||||||||||||||||||||||
dla Nr = -1 | - | funkcja zwraca liczbę pozycji z pobranej ramówki programu telewizyjnego (domyślnie), | |||||||||||||||||||||
dla Nr > -1 | - |
funkcja zwraca dane poszczególnych pozycji z pobranej ramówki programu telewizyjnego. Format tych danych jest następujący:
|
Funkcja ta zwraca do aplikacji opisy dla poszczególnych pozycji z pobranej ramówki programu telewizyjnego z listy utworzonej przez wcześniej uruchomioną funkcję Pobierz.
Funkcja ta zwraca do aplikacji kategorie dla poszczególnych pozycji z pobranej ramówki programu telewizyjnego z listy utworzonej przez wcześniej uruchomioną funkcję Pobierz.
Funkcja ta zwraca do aplikacji oznaczenia hitów (1 - oznacza hit, 0 - oznacza normalną pozycję) dla poszczególnych pozycji z pobranej ramówki programu telewizyjnego z listy utworzonej przez wcześniej uruchomioną funkcję Pobierz.
Funkcja ta zwraca do aplikacji adresy internetowe obrazków dla poszczególnych pozycji z pobranej ramówki programu telewizyjnego z listy utworzonej przez wcześniej uruchomioną funkcję Pobierz. Jeśli funkcja ta udostępniana jest przez wtyczkę, to musi też istnieć funkcja PobierzPlik, aby aplikacja mogła później pobrać nowe obrazki, których jeszcze niema w bazie programu.
Funkcja służąca do otwierania okna ustawień wtyczki.
Parametry wejściowe to: | ||
TApplication *Host | - | uchwyt aplikacji wykorzystywany do scalenia okna ustawień wtyczki z aplikacją (aby na pasku zadań nie było dodatkowego przycisku okna ustawień wtyczki). |
Funkcja zwraca wartość typu bool: | ||
true | - | gdy aplikacja ma wyświetlić listę kanałów wtyczki w edytorze list kanałów. |
false | - | gdy brak jest dalszych działań. |
Funkcja ta pobiera loga kanałów.
Aby funkcja ta mogła pobrać odpowiednie logo kanału, to najpierw musi ustalić odpowiedni adres pliku zawierającego logo kanału. W tym celu musi dysponować kodem źródłowym strony internetowej dla odpowiedniego kanału. Jeśli go nie posiada, to musi go najpierw pobrać na przykład za pomocą wbódowanej funkcji Pobierz, przy czym najpierw musi ustawić zmienną globalną ::Dekoduj na false.
Pobrane loga zapisuje się do odpowiedniego podfolderu, którym jest nazwa kanału w katalogu głównym aplikacji w folderze Ustawienia. Nazwa pliku to, w zależności od typu Logo.png lub Logo.jpg.
Parametry wejściowe to: | ||
char *Kanal | - | nazwa kanału dla którego ma być pobrane logo. |
Funkcja zwraca wartość typu bool: | ||
true | - | gdy operacja zakończyła się sukcesem. |
false | - | gdy wystąpił błąd. |
Funkcja ta służy do pobierania plików i wymagana jest między innymi do pobierania obrazków, których adresy zostały wcześniej zwrócone do aplikacji przez funkcję OdebraneObrazki. Funkcja ta, może też być wykorzystywana wewnętrznie do pobierania plików przez funkcje takie jak Pobierz czy PobierzLogo.
Parametry wejściowe to: | ||
char *Adres | - | adres internetowy pliku do pobrania, |
char *Plik | - | ścieżka i nazwa pliku pod jaką zostanie zapisany plik. |
Funkcja zwraca wartość typu bool: | ||
true | - | gdy operacja zakończyła się sukcesem. |
false | - | gdy wystąpił błąd. |
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); 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 PobierzLogo(char *Kanal); extern "C" __declspec(dllexport) bool __stdcall PobierzPlik(char *Adres,char *Plik); //--------------------------------------------------------------------------- #endif
Zawartość pliku źródłowego Kod.cpp:
//--------------------------------------------------------------------------- #include <vcl.h> #include <windows.h> #include <urlmon.h> // Należy również dodać do projektu plik urlmon.lib. #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; bool Dekoduj=true; //--------------------------------------------------------------------------- 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) { 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"; bool Stan=PobierzPlik(Adres.c_str(),Plik.c_str()); if(::Dekoduj==true) { if(Stan==true) { 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 { ::Dekoduj=true; if(Stan==true) 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 PobierzLogo(char *Kanal) { bool Stan=false; String Data=DateToStr(Date()); if(!FileExists("Pobrane\\"+String(Kanal)+"\\"+Data+".html")) { ::Dekoduj=false; Pobierz(Kanal,StrToDate(Data)); } 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. bool Status=PobierzPlik(Dane.c_str(),("Ustawienia\\"+String(Kanal)+ "\\Logo.png lub jpg").c_str()); if(Status==true) Stan=true; break; } } delete Html; } return Stan; } //--------------------------------------------------------------------------- bool __stdcall PobierzPlik(char *Adres,char *Plik) { bool Status=false; int Stan=URLDownloadToFile(0,Adres,Plik,0,0); if((Stan==S_OK)&&(FileExists(String(Plik)))) Status=true; return Status; } //---------------------------------------------------------------------------
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. |