1
1
Fork 0
Browse Source

naredil download v preteklost

pull/1/head
Anton Luka Šijanec 2 years ago
parent
commit
3713a80a0f
  1. 5
      Makefile
  2. 54
      README.md
  3. BIN
      a.out
  4. BIN
      rtv4d-dl
  5. 692
      rtv4d-dl.c
  6. 9
      test.c

5
Makefile

@ -3,6 +3,7 @@ default:
@echo - če še niste, preberite README.md in se pozanimajte o uporabi
@echo - če še niste, z \`make prepare\` namestite C \(potrebuje sudo in apt\)
@echo - če še niste, z \`make compile\` izdelajte binarne programe
@echo - če pe niste, z \`make install\` namesti v ~/.local/bin/ prej compilej!
@echo rtv4d-dl dela samo na GNU/Linux ... na oknih poskusi cygwin.
@echo to je vse, hvala.
@ -11,3 +12,7 @@ prepare:
compile:
gcc rtv4d-dl.c -o rtv4d-dl -Wall -lm -I.
install:
mkdir -p ~/.local/bin
cp ./rtv4d-dl ~/.local/bin/

54
README.md

@ -25,8 +25,12 @@ z uporabo programa se strinjate z naslednjimi stavki:
- opomba: nekateri metapodatki veljajo omejeno časa (video URL)
* prenos sličice oddaje: `rtv4d-dl slicica-oddaja <URL> [datoteka]`
- primer: `rtv4d-dl slicica-oddaja 89614963 89614963.jpg`
* prenos zadnjih dveh ur prenosa v živo: `rtv4d-dl zivo <prog.> [dolž.] [dato.]`
- primer: `rtv4d-dl zivo tv.slo1 9999999 tv.slo1.ts` (prenese vse)
* prenos zadnjih dveh ur prenosa v živo: `rtv4d-dl zivo [2] [3] [4] [5]`
- primer: `rtv4d-dl zivo slo1 slo1 9999999 9999999` (prenese vse)
- arg. 2 je program, 3 je izhodni direktorij,
4 je število sekund v preteklost, 5 je število sekund v prihodnost
* prenos podnapisov oddaje: `rtv4d-dl podnapisi <url> [datoteka]`
- primer: `rtv4d-dl podnapisi 15486024 15486024.vtt`
# dodatne informacije:
* pisanje v STDOUT: kot pot datoteke napišite `/dev/stdout`
@ -41,6 +45,7 @@ z uporabo programa se strinjate z naslednjimi stavki:
## dnevnik sprememb:
* 0.0.2 - 13. december 2020: sedaj pravilno naloži samo največjo kvaliteto, pred
tem se naloži naključna kvaliteta.
* 0.0.3 - 24. december 2020: dodano prenašanje VTT podnapisov in prenosov v živo
# o
* program je spisan 100% v C programskem jeziku
@ -54,8 +59,7 @@ z uporabo programa se strinjate z naslednjimi stavki:
naj mi pošlje `Makefile`
## formatiranje kode
* K&R komentarji
* GNUC
* K&R komentarji, GNUC
* levi zaviti oklepaj na isti vrstici kot funkcija, desni na svoji vrstici
* vrstica max. 80 znakov, upoštevajoč, da tabulator šteje za dva
* presledek za imenom funkcije in argumenti, vendar le ob deklaraciji
@ -74,30 +78,32 @@ z uporabo programa se strinjate z naslednjimi stavki:
* ker predvajanje v živo na RTVSLO trenutno potrebuje Javascript, bi bilo
uporabno narediti minimalističen HTTP/RTP strežnik, ki bi delal zahteve na RTV
in kot izhod uporabniku ponudil pretok.
- opomba: seveda predvajanje v živo deluje na VLC predvajalniku v formatu m3u8
+ primer: [https://ž.ga/tvslo1](https://ž.ga/tvslo1) v VLC network stream
* RTV za avdio/radio v živo že ponuja možnost poslušanja brez javascripta, imajo
namreč icecast2 strežnik na [mp3.rtvslo.si](mp3.rtvslo.si), tako da tega po
mojem ni potrebno izdelati še v rtv4d-dl.
* RTV4D arhiv ponuja samo videokvalitete do 720p (1280x720 pikslov). Pri
prenosu v živo pa je maksimalna velikost 1080p (1920x1080 pisklov). Če torej hočemo dobiti kvalitetno vsebino, jo moramo posneti preden gre v arhiv.
prenosu v živo pa je maksimalna velikost 1080p (1920x1080 pisklov). Če torej
hočemo dobiti kvalitetno vsebino, jo moramo posneti, preden gre v arhiv.
### dodatno o prenosu v živo
* prenos v živo ima zblojene timestampe. vsaka TS datoteka je ali 4 sekunde ali
5 sekund. sicer bi bilo vse v redu, če bi chunklist datoteka vsebovala več
kot dve uri posnetkov. Kljub temu, da streaming strežnik takoj ne zbriše
datotek in da imajo datoteke imena po vrsti, je nemogoče predvideti, katera
datoteka je potrebna ob določenem času.
* ne vemo, koliko sekund posnetkov hrani strežnik, zato predvidevamo, da je
vsak kos dolg toliko, kot tisti v kazalu, če pa imajo tisti v kazalu različne
dolžine, pa se izbere najkrajša in se zaokroži na celo sekundo na dol.
* za avtomatsko pridobitev vseh videoprogramov, ki so na voljo kot prenosi v
živo, bi bilo potrebno narediti podporo za HTTPS. zato so na voljo samo
naslednji programi: `tv.slo1`, tv.slo2`, `tv.slo3`, `tv.kp1`, `tv.mb1`,
`tv.mmctv`. programe lahko dodajate samo s spremembo izvorne kode.
* argument dolžina je število sekund od trenutnega časa do največjega zamika.
nastavitev 4 bo torej prenesla najmanj zadnje štiri sekunde. Ker TS datoteke
nimajo enake dolžine, bo pač preneseno toliko podatkov, da bo shranjeno enako
ali več sekund, kot je bilo navedenih. Če je specificiranih več kot za dve
uri sekund, oziroma več, kolikor jih ima chunklist z dolžinami, bo program
predvidel, da je vsaka datoteka dolga štiri sekunde. Ko na CDN strežniku ni
toliko sekund, kot jih uporabnik želi, bo to napisano kot OPOZORILO, naložilo
pa se bo vse, kar je na voljo. Brez argumenta dolžine se torej naloži vse, kar
CDN strežnik trenutno ima, recimo 10 ur v najvišji resoluciji 1080p.
- za bolj natančno štetje dolžin, ko se chunklist tabela konča, bi bilo
potrebno najti ali narediti sistem za pridobivanje dolžin iz TS datotek.
živo, bi bilo potrebno narediti podporo za HTTPS, zato je treba poznati
kratice programov na pamet: `slo1`, `slo2`, `slo3`, `kp1`, `mb1`, `mmctv`.
* če je število sekund v preteklost večje od vsebine, ki jo ima strežnik v
kazalu, bo shranjena vsa vsebina, ki je na strežniku za nazaj (~10 ur).
* če je število sekund v prihodnost večje od 0, bo program čakal, da izide nov
delček pretoka, in ga naložil sproti, vse do izpolnjene kvote.
* program najprej naloži v preteklost, nato v prihodnost, med nalaganjem v
prihodnost ga sicer lahko prekinete, vendar to naredite med tem, ko poteka
čakanje na nov segment, ne med nalaganjem segmenta ali tik po nalaganju.
* prenos v živo se shrani kot m3u8 playlist in mpeg ts datoteke. te datoteke
se lahko normalno združi v eno z ukazom `cat *.ts > zdruzene.ts` in se odpre
kar zdruzene.ts v VLC predvajalniku. VLC podpira tudi direktno odprtje
playlist.m3u8 datoteke in branje po kosih.
* če program ni bil prekinjen, bo po končanem prenosu v stdout napisal
metapodatke pretoka v živo.

BIN
a.out

Binary file not shown.

BIN
rtv4d-dl

Binary file not shown.

692
rtv4d-dl.c

@ -4,6 +4,11 @@
#include <string.h>
#include <math.h>
#include <tcp.c>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#define NIZ_DODATEK(a) #a
#define NIZ(a) NIZ_DODATEK(a)
#define RTV_CLIENT_ID "82013fb3a531d5414f478747c1aca622" /* enak za vse */
@ -27,8 +32,9 @@
#define RTV_TEST_PROGRAM "SLO1"
#define RTV_TEST_OBJAVLJENO "2010-12-03 23:20:10"
#define RTV_TEST_PREDVAJANO "2010-12-03 23:20:10"
#define RTV_TEST_TIP_POSNETKA 4D_VIDEO_TIP
#define RTV_TEST_SLICICA "http://img.rtvslo.si/_up/ava/ava_misc/show_logos" \
#define RTV_TEST_TIP_POSNETKA RTV_VIDEO_TIP
#define RTV_SLD "rtvslo.si"
#define RTV_TEST_SLICICA "http://img." RTV_SLD "/_up/ava/ava_misc/show_logos" \
"/VREME_VECERNO-980.jpg"
#define RTV_TEST_KONTROLNA_VREDNOST 1186735842
#define RTV_TEST_VELIKOST 9396765
@ -48,18 +54,73 @@
"\r\nAccept: */*\r\nX-Requested-With: tcp.c (" __FILE__ ":" NIZ(__LINE__) \
")\r\nConnection: close\r\n\r\n"
#define RTV_HTTP_TIMEOUT 69 /* sekund */
#define RTV_NE_BO_POSLAL NULL /* "ToJeMogočeBackdoor!" */ /* bere več znakov */
#define RTV_API_META_URL "http://api.rtvslo.si/ava/getRecordingDrm/" \
#define RTV_NE_BO_POSLAL NULL /* bere več znakov */
#define RTV_API_META_URL "http://api." RTV_SLD "/ava/getRecordingDrm/" \
"%u?client_id=" RTV_CLIENT_ID
#define RTV_API_META_URL_SIZEOF 128 /* vključno z nul znakom */
#define RTV_API_MEDIA_URL "http://api.rtvslo.si/ava/getMedia/%u/?client_id=" \
#define RTV_API_MEDIA_URL "http://api." RTV_SLD "/ava/getMedia/%u/?client_id=" \
RTV_CLIENT_ID "&jwt=%s"
#define RTV_API_MEDIA_URL_SIZEOF 64 + RTV_CLIENT_ID_SIZEOF + RTV_JWT_SIZEOF
#define RTV_JWT_SIZEOF 43+1
#define RTV_PREDVAJALNIK_URL "http://4d.rtvslo.si/arhiv/v/%u"
#define RTV_PREDVAJALNIK_URL_SIZEOF 32+1 + 12
#define RTV_PREDVAJALNIK_URL "http://4d." RTV_SLD "/arhiv/v/%u"
#define RTV_PREDVAJALNIK_URL_SIZEOF (32+1 + 12)
#define RTV_VER "0.0.3"
#define RTV_ZIVO_PROGRAM_SIZEOF 12
#define RTV_API_ZIVO_URL \
"http://api." RTV_SLD "/ava/getLiveStream/tv.%." \
NIZ(RTV_ZIVO_PROGRAM_SIZEOF) "s?client_id=" RTV_CLIENT_ID
#define RTV_API_ZIVO_URL_SIZEOF (64 + 32 + 1 + RTV_ZIVO_PROGRAM_SIZEOF)
#define RTV_HTTPS_V_HTTP(url) \
if (url[4] == 's') { memmove((url)+4, (url)+5, strlen((url)+5)+1); }
#define RTV_ZCARON 4294967237
#define strtollu strtoull
#define strtolu strtoul
#define strtolld strtoll
#define strtold strtol
#define strtod strtol
#define strtou strtoul
#define RTV_JSON_INIT() \
char * RTV_JSON_cp; size_t RTV_JSON_i, RTV_JSON_globina; char RTV_JSON_c;
#define RTV_JSON_VALUE(str, i, key) (str+i+strlen(key)+2)
#define RTV_JSON_TIP_u unsigned int
#define RTV_JSON_TIP_s char
#define RTV_JSON_OBLIKA_s(imem, format, loc) \
RTV_JSON_c = RTV_JSON_cp[0]; \
RTV_JSON_cp[0] = '\0'; /* omejimo json string, ne potrebujemo strncpy */ \
imem##_sizeof = sizeof(char)*(strlen(loc)+1+RTV_P_SIZEOF); \
imem = realloc(imem, imem##_sizeof); \
strcpy(imem, loc); \
RTV_JSON_cp[0] = RTV_JSON_c; /* ponastavimo originalno vrednost */
#define RTV_JSON_OBLIKA_u(imem, format, loc) /* -1: št niso v "" v JSON */ \
imem = strto##format(loc, NULL, 10);
#define RTV_JSON_IZPOLNI(imem, format, splitter, loc) \
do { RTV_JSON_cp = strchr(loc, splitter); \
if ( RTV_JSON_cp == NULL) { \
RTV_NAPISI(OPOZORILO, "RTV_JSON: napaka pri: " #imem); \
} else { \
RTV_JSON_OBLIKA_##format(imem, format, loc) \
RTV_NAPISI(HROSC, "RTV_JSON: " #imem " => %" #format, \
imem); \
} } while (0);
#define RTV_JSON(str, strl, key, out, fmt, spl, otr) /* strl je strlen */ \
do { \
for (RTV_JSON_i = 0; RTV_JSON_i < strl; RTV_JSON_i++) { /* keyss=sizeof */ \
if (otr != NULL) { \
if (str[RTV_JSON_i] == '}' && RTV_JSON_globina > 0) RTV_JSON_globina--;\
if (str[RTV_JSON_i] == '{') \
if (strncmp(otr, str+RTV_JSON_i-(2+strlen(otr)), strlen(otr)) == 0) \
RTV_JSON_globina++; \
} \
if ( (RTV_JSON_globina > 0 || otr == NULL) \
&& strncmp(str+RTV_JSON_i, key, strlen(key)) == 0) { \
RTV_JSON_IZPOLNI(out, fmt, spl, RTV_JSON_VALUE(str, RTV_JSON_i, key)); \
break; \
} \
} \
} while (0);
#define RTV_FREE(param) do { free(param); param = NULL; } while (0)
#define RTV_HTTP_SUCCESS(koda) ((koda / 100) == 2) /* če je koda 2xx */
#define RTV_ZIVO_P_DOLZINA 10
struct meta_oddaja {
size_t naslov_sizeof;
char * naslov; /* Vreme ob 22h */
@ -90,37 +151,75 @@ struct meta_oddaja {
char predvajalnik_url[RTV_PREDVAJALNIK_URL_SIZEOF]; /* http://4d.rtvslo.... */
size_t posnetek_url_sizeof;
char * posnetek_url; /* http://progressive.rtvslo.si/encrypted00/2010/12... */
char * podnapisi_url; /* http://img.rtvslo.si/_up/ava/ava_misc/subs/2020... */
size_t podnapisi_url_sizeof; /* upam, da nikoli ni več kot ena datoteka. */
};
struct meta_oddaja * meta_oddaja_alloc () {
struct meta_oddaja * m = malloc(sizeof(struct meta_oddaja));
m->naslov = malloc(sizeof(char)*RTV_P_SIZEOF);m->naslov_sizeof = RTV_P_SIZEOF;
m->zanri = malloc(sizeof(char)*RTV_P_SIZEOF); m->zanri_sizeof = RTV_P_SIZEOF;
m->opis = malloc(sizeof(char)*RTV_P_SIZEOF); m->opis_sizeof = RTV_P_SIZEOF;
m->tip_oddaje_ime=malloc(sizeof(char)*RTV_P_SIZEOF);
m->tip_oddaje_ime_sizeof = RTV_P_SIZEOF;
m->program = malloc(sizeof(char)*RTV_P_SIZEOF);m->program_sizeof=RTV_P_SIZEOF;
m->slicica = malloc(sizeof(char)*RTV_P_SIZEOF);m->slicica_sizeof=RTV_P_SIZEOF;
m->jwt = malloc(sizeof(char)*RTV_P_SIZEOF); m->jwt_sizeof=RTV_P_SIZEOF;
m->objavljeno = malloc(sizeof(char)*RTV_P_SIZEOF);
m->objavljeno_sizeof = RTV_P_SIZEOF;
m->predvajano = malloc(sizeof(char)*RTV_P_SIZEOF);
m->predvajano_sizeof = RTV_P_SIZEOF;
m->posnetek_url = malloc(sizeof(char)*RTV_P_SIZEOF);
m->posnetek_url_sizeof = RTV_P_SIZEOF;
#define RTV_META_ALLOC(param) \
param = malloc(sizeof(char)*RTV_P_SIZEOF); param##_sizeof = RTV_P_SIZEOF; \
param[0] = '\0'; /* da ga nastavimo na prazno vrednost, ne na fuckery*/
RTV_META_ALLOC(m->naslov);
RTV_META_ALLOC(m->zanri);
RTV_META_ALLOC(m->opis);
RTV_META_ALLOC(m->tip_oddaje_ime);
RTV_META_ALLOC(m->program);
RTV_META_ALLOC(m->slicica);
RTV_META_ALLOC(m->jwt);
RTV_META_ALLOC(m->objavljeno);
RTV_META_ALLOC(m->predvajano);
RTV_META_ALLOC(m->posnetek_url);
RTV_META_ALLOC(m->podnapisi_url);
return m;
}
int meta_oddaja_free (struct meta_oddaja * m) {
free(m->naslov); m->naslov = NULL;
free(m->zanri); m->zanri = NULL;
free(m->opis); m->opis = NULL;
free(m->tip_oddaje_ime); m->tip_oddaje_ime = NULL;
free(m->program); m->program = NULL;
free(m->slicica); m->slicica = NULL;
free(m->jwt); m->jwt = NULL;
free(m->objavljeno); m->objavljeno = NULL;
free(m->predvajano); m->predvajano = NULL;
free(m->posnetek_url); m->posnetek_url = NULL;
free(m); m = NULL;
RTV_FREE(m->naslov);
RTV_FREE(m->zanri);
RTV_FREE(m->opis);
RTV_FREE(m->tip_oddaje_ime);
RTV_FREE(m->program);
RTV_FREE(m->slicica);
RTV_FREE(m->jwt);
RTV_FREE(m->objavljeno);
RTV_FREE(m->predvajano);
RTV_FREE(m->posnetek_url);
RTV_FREE(m->podnapisi_url);
RTV_FREE(m);
return 0;
}
struct rtv_zivo_meta {
char program[RTV_ZIVO_PROGRAM_SIZEOF]; /* slo1, slo2 */
unsigned int sedanjost; /* recimo 5580, številka zadnjega kosa */
unsigned int prvi; /* recimo 1234, številka prvega kosa, ki ga ima strežnik */
unsigned int dolzina; /* koliko dolg je en kos */
unsigned int diskrepanca; /* 1, če niso vsi kosi enako dolgi, 0 drugače */
unsigned int prenesenih_kosov_preteklost;
unsigned int prenesenih_kosov_prihodnost;
unsigned int preteklost; /* število sekund, ki naj jih prenesem za nazaj */
unsigned int prihodnost; /* število sekund, ki naj jih prenesem za naprej */
char * seznam_predvajanja_url; /* http://30-rtvslo-tv-slo1.../playlist.m3u8 */
size_t seznam_predvajanja_url_sizeof;
char * kazalo_url; /* http://30-rtvslo-tv-slo-tv.../chunklist_b4128000.m3u8 */
size_t kazalo_url_sizeof;
char * kos_format; /* http://30-rtvslo-tv-slo-tv-sl.../media_b4128000_%u.ts */
size_t kos_format_sizeof;
char * api_url; /* http://api.rtvslo.si/ava/getLiveStream/tv.slo1?client... */
size_t api_url_sizeof;
};
struct rtv_zivo_meta * rtv_zivo_meta_alloc () {
struct rtv_zivo_meta * m = malloc(sizeof(struct rtv_zivo_meta));
RTV_META_ALLOC(m->seznam_predvajanja_url);
RTV_META_ALLOC(m->kazalo_url);
RTV_META_ALLOC(m->kos_format);
RTV_META_ALLOC(m->api_url);
return m;
}
int rtv_zivo_meta_free (struct rtv_zivo_meta * m) {
RTV_FREE(m->seznam_predvajanja_url);
RTV_FREE(m->kazalo_url);
RTV_FREE(m->kos_format);
RTV_FREE(m->api_url);
RTV_FREE(m);
return 0;
}
int niz_realloc (char * s, size_t * v) {
@ -141,6 +240,7 @@ int http_get (/* const */ char * u, FILE * r) { /* url ostane enak */
size_t header_sizeof = 0;
long long int contentlength = -69420;
char * request_buf; /* za request buffer */
int response_code = -69420;
#define RTV_URL_HOST (u+7)
if (u == NULL) {
RTV_NAPISI(NAPAKA, "URL je null!");
@ -170,33 +270,36 @@ int http_get (/* const */ char * u, FILE * r) { /* url ostane enak */
}
t = *k;
*k = '\0';
RTV_NAPISI(INFO, "Vzpostavljam TCP povezavo na http://%s:%d ...",
RTV_URL_HOST, p);
RTV_NAPISI(HROSC, "http://%s:%d/%s",
RTV_URL_HOST, p, path);
c = spawn_conn(RTV_URL_HOST, p);
if (c < 0) {
RTV_NAPISI(NAPAKA, "TCP povezava ni uspela!");
returnstatus = 4;
goto http_get_returncleanly;
} else {
RTV_NAPISI(INFO, "Povezan na strežnik.");
RTV_NAPISI(HROSC, "Povezan na strežnik.");
}
request_buf = malloc (sizeof(char) * ( sizeof(RTV_HTTP_GET)
+ strlen(RTV_URL_HOST)+ strlen(path) + 1 ));
sprintf(request_buf, RTV_HTTP_GET, path, RTV_URL_HOST); /* =dovolj prostora */
RTV_NAPISI(INFO, "Pošiljam %lu bajtov ...", strlen(request_buf));
RTV_NAPISI(HROSC, "Pošiljam %lu bajtov ...", strlen(request_buf));
ret = sync_write(c, request_buf, strlen(request_buf), RTV_HTTP_TIMEOUT);
if (ret != 0) {
returnstatus = 5;
RTV_NAPISI(NAPAKA, "TCP časovna omejitev pri pošiljanju je potekla");
goto http_get_returncleanly;
} else {
RTV_NAPISI(INFO, "Uspešno poslano.");
RTV_NAPISI(HROSC, "Uspešno poslano.");
}
headerstream = open_memstream(&header, &header_sizeof);
while (1) {
rewind(headerstream);
ret = read_until(c, headerstream, RTV_HTTP_TIMEOUT, "\n", -1); /* unsig!*/
fflush(headerstream);
if (response_code == -69420 && strchr(header, ' ') != NULL) {
response_code = atoi(strchr(header, ' ')+1);
}
if (ret != 0) {
returnstatus = 6;
RTV_NAPISI(NAPAKA, "Branje headerja ni uspelo!");
@ -205,15 +308,15 @@ int http_get (/* const */ char * u, FILE * r) { /* url ostane enak */
if (strncasecmp("Content-Length: ", header, strlen("Content-Length: "))
== 0) {
contentlength = strtoll(header+16, NULL, 10);
RTV_NAPISI(INFO, "Pridobil %lld bajtni odgovor.", contentlength);
RTV_NAPISI(HROSC, "Pridobil %lld bajtni odgovor.", contentlength);
}
if (strncmp("\r\n", header, 2) == 0 || header[0] == '\n')
break;
}
if (contentlength == -69420) {
RTV_NAPISI(OPOZORILO, "Manjka Content-Length, berem do konca.");
RTV_NAPISI(HROSC, "Manjka Content-Length, berem do konca."); /* legalno */
} else {
RTV_NAPISI(INFO, "Začetek telesa odgovora. Berem in pišem.");
RTV_NAPISI(HROSC, "Začetek telesa odgovora. Berem in pišem.");
}
fclose(headerstream);
ret = read_until(c, r, RTV_HTTP_TIMEOUT, RTV_NE_BO_POSLAL, contentlength);
@ -222,7 +325,7 @@ int http_get (/* const */ char * u, FILE * r) { /* url ostane enak */
RTV_NAPISI(NAPAKA, "Branje in pisanje telesa odgovora ni uspelo!");
goto http_get_returncleanly;
}
RTV_NAPISI(INFO, "Prejel in uspešno shranil/prebral HTTP odgovor.");
RTV_NAPISI(HROSC, "Prejel in uspešno shranil/prebral HTTP odgovor.");
http_get_returncleanly:
free(request_buf);
request_buf = NULL;
@ -232,138 +335,72 @@ int http_get (/* const */ char * u, FILE * r) { /* url ostane enak */
RTV_NAPISI(OPOZORILO, "TCP povezave ni uspelo prekiniti");
*k = t;
u[6] = '/';
if (returnstatus == 0) {
returnstatus = response_code;
}
return returnstatus;
}
int rtv_meta_izpolni(struct meta_oddaja * m) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull"
int returnstatus = 0;
FILE * odgstream;
char * odg;
size_t sizeloc;
size_t i, j;
unsigned short int nasel_addaptivemedia = 0; /* glej iskanje stream URLja */
char * metakeys[] = {"\"title\"", "\"showId\"", "\"genre\"", \
"\"description\"", "\"showDescription\"", "\"duration\"", "\"jwt\"", \
"\"showName\"", "\"source\"", "\"publishDate\"", "\"mediaType\"", \
"\"orig\"", "\"broadcastDate\"", /* getMedia query: */ "\"http\"", \
"\"https\"", "\"addaptiveMedia\"" };
char * cp;
#define RTV_META_IZPOLNI_METAKEYS_SIZEOF 13 /* hkrati offset za getMedia */
#define RTV_META_IZPOLNI_METAKEYS_GETMEDIA_FINAL \
(RTV_META_IZPOLNI_METAKEYS_SIZEOF+3) /* zadnji+1 za getMedia */
#define RTV_META_IZPOLNI_VALUE (odg+i+strlen(metakeys[j])+2)
#define RTV_META_IZPOLNI_VALUE_INTERNAL RTV_META_IZPOLNI_VALUE
RTV_JSON_INIT();
snprintf(m->get_meta_url, RTV_API_META_URL_SIZEOF, RTV_API_META_URL, m->id);
snprintf(m->predvajalnik_url, RTV_PREDVAJALNIK_URL_SIZEOF, RTV_PREDVAJALNIK_URL, m->id);
odgstream = open_memstream(&odg, &sizeloc);
returnstatus = http_get(m->get_meta_url, odgstream); /* shranimo metapodat. */
if (returnstatus != 0) {
RTV_NAPISI(NAPAKA, "Zahteva za metapodatke iz API strežnika je spodletela");
if (!RTV_HTTP_SUCCESS(returnstatus)) {
RTV_NAPISI(NAPAKA, "API zahteva je spodletela s kodo %d", returnstatus);
goto rtv_meta_izpolni_returncleanly;
}
} else returnstatus = 0;
fflush(odgstream);
for (i = 0; i < sizeloc; i++) {
for (j = 0; j < RTV_META_IZPOLNI_METAKEYS_SIZEOF; j++) {
if (strncmp(odg+i, metakeys[j], strlen(metakeys[j])) == 0) {
switch (j) {
case 0: /* title */
#define strtollu strtoull
#define strtolu strtoul
#define strtolld strtoll
#define strtold strtol
#define strtod strtol
#define strtou strtoul
#define RTV_META_IZPOLNI_V(imem, format, tip) /* za variabilne nize */ \
cp[0] = '\0'; /* omejimo json string, ne potrebujemo strncpy */ \
m->imem = realloc(m->imem, sizeof(tip) * \
strlen(RTV_META_IZPOLNI_VALUE_INTERNAL)+1); \
m->imem##_sizeof = strlen(RTV_META_IZPOLNI_VALUE_INTERNAL)+1; \
strcpy(m->imem, RTV_META_IZPOLNI_VALUE_INTERNAL);
#define RTV_META_IZPOLNI_I(imem, format, tip) /* za številke */ \
m->imem = strto##format(RTV_META_IZPOLNI_VALUE_INTERNAL, NULL, 10);
#define RTV_META_IZPOLNI(imem, oblika, format, splitter, tip) \
do { cp = strchr(RTV_META_IZPOLNI_VALUE_INTERNAL, splitter); \
if (cp == NULL) { \
RTV_NAPISI(OPOZORILO, "Napaka pri iskanju podatka " #imem); \
/* strcpy(m->imem, "Napaka pri pridobivanju."); */ /* ni vse s*/ \
} else { \
oblika(imem, format, tip) \
RTV_NAPISI(HROSC, "Shranil metapodatek " #imem ": %" #format, \
m->imem); \
} } while (0)
/* #pragma GCC diagnostic ignored "-Wint-conversion" */ /* surpressaš opozor. */
RTV_META_IZPOLNI(naslov, RTV_META_IZPOLNI_V, s, '"', char);
break;
case 1: /* showId */
RTV_META_IZPOLNI(tip_oddaje_id, RTV_META_IZPOLNI_I, u, '"', unsigned int);
break;
case 2: /* genre je "asdasd","asdasd","sdfsfd" */
RTV_META_IZPOLNI(zanri, RTV_META_IZPOLNI_V, s, ']', char);
memmove(m->zanri, (m->zanri)+1, strlen(m->zanri)+1);
break;
case 3: /* description */
RTV_META_IZPOLNI(opis, RTV_META_IZPOLNI_V, s, '"', char);
break;
case 4: /* showDescription */
if (m->opis[0] == '\0') { /* če je prejšnji spodletel */
RTV_META_IZPOLNI(opis, RTV_META_IZPOLNI_V, s, '"', char);
}
break;
case 5: /* duration */
#undef RTV_META_IZPOLNI_VALUE_INTERNAL
#define RTV_META_IZPOLNI_VALUE_INTERNAL RTV_META_IZPOLNI_VALUE-1
RTV_META_IZPOLNI(dolzina, RTV_META_IZPOLNI_I, u, '"', unsigned int);
#undef RTV_META_IZPOLNI_VALUE_INTERNAL
#define RTV_META_IZPOLNI_VALUE_INTERNAL RTV_META_IZPOLNI_VALUE
break;
case 6: /* jwt */
RTV_META_IZPOLNI(jwt, RTV_META_IZPOLNI_V, s, '"', char);
if (RTV_JWT_SIZEOF != m->jwt_sizeof) {
RTV_NAPISI(OPOZORILO, "Shranil nepričakovano dolg JWT! Je vdor?");
}
break;
case 7: /* showName */
RTV_META_IZPOLNI(tip_oddaje_ime, RTV_META_IZPOLNI_V, s, '"', char);
break;
case 8: /* source */
RTV_META_IZPOLNI(program, RTV_META_IZPOLNI_V, s, '"', char);
break;
case 9: /* publishDate */
RTV_META_IZPOLNI(objavljeno, RTV_META_IZPOLNI_V, s, '"', char);
break;
case 10: /* mediaType */
switch (RTV_META_IZPOLNI_VALUE[0]) {
case 'v':
m->tip_posnetka = RTV_VIDEO_TIP;
break;
case 'a':
m->tip_posnetka = RTV_AUDIO_TIP;
break;
default:
m->tip_posnetka = RTV_NEPOZNAN_TIP;
break;
}
break;
case 11: /* orig */ /* sličica */
RTV_META_IZPOLNI(slicica, RTV_META_IZPOLNI_V, s, '"', char);
break;
case 12: /* broadcastDate */
RTV_META_IZPOLNI(predvajano, RTV_META_IZPOLNI_V, s, '"', char);
break;
/* #pragma GCC diagnostic warning "-Wint-conversion" */ /* undo */
default:
RTV_NAPISI(OPOZORILO, "Doseg nedefinirane kode!");
}
}
RTV_JSON(odg, sizeloc, "\"title\"", m->naslov, s, '"', NULL);
/* pri številkah je vseeno, kaj je spl */
RTV_JSON(odg, sizeloc, "\"showId\"", m->tip_oddaje_id, u, '"', NULL);
RTV_JSON(odg, sizeloc, "\"genre\"", m->zanri, s, ']', NULL);
memmove(m->zanri, (m->zanri)+1, strlen(m->zanri)+1);
RTV_JSON(odg, sizeloc, "\"description\"", m->opis, s, '"', NULL);
if (m->opis[0] == '\0') /* če je prejšnji spodletel */
RTV_JSON(odg, sizeloc, "\"showDescription\"", m->opis, s, '"', NULL);
RTV_JSON(odg, sizeloc, "\"duration\"", m->dolzina, u, '"', NULL);
RTV_JSON(odg, sizeloc, "\"jwt\"", m->jwt, s, '"', NULL);
if (RTV_JWT_SIZEOF != m->jwt_sizeof)
RTV_NAPISI(OPOZORILO, "Shranil nepričakovano dolg JWT! Je vdor?");
RTV_JSON(odg, sizeloc, "\"showName\"", m->tip_oddaje_ime, s, '"', NULL);
RTV_JSON(odg, sizeloc, "\"source\"", m->program, s, '"', NULL);
RTV_JSON(odg, sizeloc, "\"publishDate\"", m->objavljeno, s, '"', NULL);
/* uporabimo kar m->slicica za začasno shrambo mediaType (: */
RTV_JSON(odg, sizeloc, "\"mediaType\"", m->slicica, s, '"', NULL);
switch (m->slicica[0]) {
case 'v':
m->tip_posnetka = RTV_VIDEO_TIP;
break;
case 'a':
m->tip_posnetka = RTV_AUDIO_TIP;
break;
default:
m->tip_posnetka = RTV_NEPOZNAN_TIP;
break;
}
/* sedaj pa m->slicica napolnimo s pravilnim tekstom */
RTV_JSON(odg, sizeloc, "\"orig\"", m->slicica, s, '"', NULL);
RTV_JSON(odg, sizeloc, "\"broadcastDate\"", m->predvajano, s, '"', NULL);
m->podnapisi_url[0] = '\0';
RTV_JSON(odg, sizeloc, "\"file\"", m->podnapisi_url, s, '"', NULL);
if (m->podnapisi_url[0] != '\0') {
RTV_HTTPS_V_HTTP(m->podnapisi_url);
}
snprintf(m->get_media_url, RTV_API_MEDIA_URL_SIZEOF, RTV_API_MEDIA_URL, m->id, m->jwt);
rewind(odgstream);
fflush(odgstream);
returnstatus = http_get(m->get_media_url, odgstream); /* shranimo video url */
if (returnstatus != 0) {
if (!RTV_HTTP_SUCCESS(returnstatus)) {
RTV_NAPISI(NAPAKA, "Zahteva za ključ videa iz API strežnika je spodletela");
goto rtv_meta_izpolni_returncleanly;
}
} else returnstatus = 0;
fflush(odgstream);
/*
* sedaj pridobimo direktni URL do mp4 datoteke, ki ima keylockhash v GET
@ -373,45 +410,25 @@ int rtv_meta_izpolni(struct meta_oddaja * m) {
* bo ta vedno največji, če pa obstaja samo en stream, pa addaptiveMedia
* podobjekta sploh ne bo. torej, če se je string addaptiveMedia pojavil
* tik pred tem URLjem, bo ta najboljši in lahko nehamo. */
for (i = 0; i < ftell(odgstream); i++) {
for (j = RTV_META_IZPOLNI_METAKEYS_SIZEOF;
j < RTV_META_IZPOLNI_METAKEYS_GETMEDIA_FINAL; j++) {
if (strncmp(odg+i, metakeys[j], strlen(metakeys[j])) == 0) {
switch (j-RTV_META_IZPOLNI_METAKEYS_SIZEOF) {
case 0: /* http */ /* videofile */
RTV_META_IZPOLNI(posnetek_url, RTV_META_IZPOLNI_V, s, '"', char);
if (nasel_addaptivemedia == 1) {
RTV_NAPISI(HROSC, "Izmed več streamov izbral najboljšega.");
goto rtv_meta_izpolni_naselnajboljsistream;
}
nasel_addaptivemedia = 0;
break;
case 1: /* https */
if (m->posnetek_url[0] == '\0') {
RTV_META_IZPOLNI(posnetek_url, RTV_META_IZPOLNI_V, s, '"',
char);
fprintf(stderr, "test: %s\n", m->posnetek_url);
memmove((m->posnetek_url)+4, (m->posnetek_url)+5,
strlen((m->posnetek_url)+5)+1);
RTV_NAPISI(HROSC, "Popravil HTTPS URL na HTTP");
if (nasel_addaptivemedia == 1) {
RTV_NAPISI(HROSC, "Izmed več streamov izbral najboljšega.");
goto rtv_meta_izpolni_naselnajboljsistream;
}
}
nasel_addaptivemedia = 0;
break;
case 2: /* addaptiveMedia */
nasel_addaptivemedia = 1;
RTV_NAPISI(HROSC, "Naslednji najden pretok bo najboljši.");
break;
default:
RTV_NAPISI(OPOZORILO, "Doseg nedefinirane kode; case=%lu",
j-RTV_META_IZPOLNI_METAKEYS_SIZEOF);
}
}
}
} /* endfor: for (i = 0; i < ftell(odgstream); i++) */
m->posnetek_url[0] = '\0';
RTV_JSON(odg, sizeloc, "\"http\"", m->posnetek_url, s, '"',
"addaptiveMedia");
if (m->posnetek_url[0] != '\0')
goto rtv_meta_izpolni_naselnajboljsistream;
RTV_JSON(odg, sizeloc, "\"https\"", m->posnetek_url, s, '"',
"addaptiveMedia");
if (m->posnetek_url[0] != '\0') {
RTV_HTTPS_V_HTTP(m->posnetek_url);
goto rtv_meta_izpolni_naselnajboljsistream;
}
RTV_JSON(odg, sizeloc, "\"http\"", m->posnetek_url, s, '"', NULL);
if (m->posnetek_url[0] != '\0')
goto rtv_meta_izpolni_naselnajboljsistream;
RTV_JSON(odg, sizeloc, "\"https\"", m->posnetek_url, s, '"', NULL);
if (m->posnetek_url[0] != '\0') {
RTV_HTTPS_V_HTTP(m->posnetek_url);
goto rtv_meta_izpolni_naselnajboljsistream;
}
rtv_meta_izpolni_naselnajboljsistream:
rtv_meta_izpolni_returncleanly:
@ -419,28 +436,191 @@ int rtv_meta_izpolni(struct meta_oddaja * m) {
free(odg);
odg = NULL;
return returnstatus;
#pragma GCC diagnostic pop
}
int rtv_zivo_izpolni(struct rtv_zivo_meta * m) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull"
int returnstatus = 0;
FILE * odgstream;
char * odg;
size_t sizeloc;
size_t i = 0;
char * temp = malloc(sizeof(char)*6);
size_t temp_sizeof = 6;
char * e; /* char pointer for the memes */
int j; /* int for the memes */
RTV_JSON_INIT();
snprintf(m->api_url, RTV_API_ZIVO_URL_SIZEOF,
RTV_API_ZIVO_URL, m->program);
odgstream = open_memstream(&odg, &sizeloc);
returnstatus = http_get(m->api_url, odgstream);
if (!RTV_HTTP_SUCCESS(returnstatus)) {
RTV_NAPISI(NAPAKA, "Napaka %d pri zahtevi na API strežnik.", returnstatus);
returnstatus = 1;
goto rtv_zivo_izpolni_returncleanly;
} else returnstatus = 0;
fflush(odgstream);
RTV_JSON(odg, sizeloc, "\"streamer\"", m->seznam_predvajanja_url, s, '"',
NULL);
RTV_HTTPS_V_HTTP(m->seznam_predvajanja_url);
RTV_JSON(odg, sizeloc, "\"streamer\"", m->kazalo_url, s, '"', NULL);
RTV_JSON(odg, sizeloc, "\"streamer\"", m->kos_format, s, '"', NULL);
m->kazalo_url[strlen(m->kazalo_url)] = '/'; /* ja, allocata se dodaten ram */
m->kos_format[strlen(m->kos_format)] = '/'; /* ja, allocata se dodaten ram */
RTV_HTTPS_V_HTTP(m->kazalo_url);
RTV_JSON(odg, sizeloc, "\"file\"", temp, s, '"', NULL);
m->seznam_predvajanja_url_sizeof =
strlen(m->seznam_predvajanja_url)+strlen(temp)+1;
m->seznam_predvajanja_url = realloc(m->seznam_predvajanja_url,
sizeof(char) * m->seznam_predvajanja_url_sizeof);
strcat(m->seznam_predvajanja_url, temp); /* ja, je varno */
/* če obstaja ?DVR na koncu, bo vsebina gzipana, to nas samo moti */
strchrnul(m->seznam_predvajanja_url, '?')[0] = '\0'; /* odstrani parametre */
RTV_HTTPS_V_HTTP(m->seznam_predvajanja_url);
rewind(odgstream);
http_get(m->seznam_predvajanja_url, odgstream);
for (i = 0; i < ftell(odgstream); i++) {
if (odg[i] == '\n' && odg[i+1] != '#') {
e = strchr(odg+i+1, '\r');
if (strchr(odg+i+1, '\n') > e) /* 1080p je najvišja resolucija => */
e = strchr(odg+i+1, '\n'); /* prvo kazalo je najvišja resolucija */
if (e != NULL) {
j = e[0];
e[0] = '\0';
}
m->kazalo_url_sizeof = strlen(m->kazalo_url)+strlen(odg+i+1)+1;
m->kazalo_url = realloc(m->kazalo_url, sizeof(char)*m->kazalo_url_sizeof);
strcat(m->kazalo_url, odg+i+1); /* ja, je varno /\ */
if (e != NULL)
e[0] = j; /* popravimo nazaj */
break; /* spet, potrebujemo samo prvi t. i. "chunklist". */
}
}
RTV_NAPISI(HROSC, "kazalo_url => %s", m->kazalo_url);
rewind(odgstream);
returnstatus = http_get(m->kazalo_url, odgstream);
if (!RTV_HTTP_SUCCESS(returnstatus)) {
RTV_NAPISI(NAPAKA, "Napaka %d pri zahtevi na API strežnik.", returnstatus);
returnstatus = 1;
goto rtv_zivo_izpolni_returncleanly;
} else returnstatus = 0;
e = strstr(odg, "#EXT-X-TARGETDURATION:");
if (e != NULL) {
m->dolzina = atoi(e+strlen("#EXT-X-TARGETDURATION:"));
RTV_NAPISI(HROSC, "(v prvo) dolžina kosa je %u sekund", m->dolzina);
} else {
e = strstr(odg, "#EXTINF:");
if (e != NULL) {
m->dolzina = atoi(e+strlen("#EXTINF:"));
RTV_NAPISI(HROSC, "(v drugo) dolžina kosa je %u sekund", m->dolzina)
} else {
m->dolzina = RTV_ZIVO_P_DOLZINA;
RTV_NAPISI(OPOZORILO, "nisem našel dolžine kosa-uporabim %u", m->dolzina);
}
}
e = strstr(odg, "#EXT-X-MEDIA-SEQUENCE:");
if (e != NULL) {
m->prvi = atoi(e+strlen("#EXT-X-MEDIA-SEQUENCE:")); /* prvi v kazalu */
RTV_NAPISI(HROSC, "našel sekvenčno številko %u", m->prvi);
} else {
RTV_NAPISI(NAPAKA, "pri iskanju MEDIA-SEQUENCE: ne morem narediti formata"
". poskusite znova nekajkrat. je RTV strežnik spet GZIPpal? :shrug:");
returnstatus = 2;
goto rtv_zivo_izpolni_returncleanly;
}
m->sedanjost = -69420;
m->prenesenih_kosov_preteklost = 0;
m->prenesenih_kosov_prihodnost = 0;
for (i = 0; i < ftell(odgstream); i++) {
if (odg[i+1] != '#' && odg[i] == '\n') {
e = strchr(odg+i+1, '\r');
if (strchr(odg+i+1, '\n') > e)
e = strchr(odg+i+1, '\n');
j = -69420;
if (e != NULL) {
j = e[0];
e[0] = '\0';
}
snprintf(temp, temp_sizeof, "%u", m->prvi);
e = strstr(odg+i+1, temp);
if (e != NULL) {
m->kos_format_sizeof = ((strchr(odg+i+1, '\n')
?(odg+i+1)-strchr(odg+i+1, '\n'):strlen(odg+i+1))+1+RTV_P_SIZEOF
)*sizeof(char);
m->kos_format = realloc(m->kos_format, m->kos_format_sizeof);
strncat(m->kos_format, odg+i+1, m->kos_format_sizeof/sizeof(char));
if (strchr(m->kos_format, '\r')) strchr(m->kos_format, '\r')[0] = '\0';
if (strchr(m->kos_format, '\n')) strchr(m->kos_format, '\n')[0] = '\0';
e = strstr(m->kos_format, temp);
memmove(e+2, e+strlen(temp), strlen(temp)+1); /* naredimo prostor 2 */
e[0] = '%'; e[1] = 'u'; /* napišemo format v prostorček */
RTV_HTTPS_V_HTTP(m->kos_format);
RTV_NAPISI(HROSC, "m->kos_format => %s", m->kos_format);
}
e = strrchr(m->kos_format+strlen("http://"), '/')+1;
if (strchr(m->kos_format, '%') != NULL && e != NULL) {
sscanf(odg+i+1, e, &(m->sedanjost));
}
if (j != -69420)
*(odg+i+strlen(odg+i)) = j; /* popravimo */
}
}
if (m->sedanjost == -69420) {
RTV_NAPISI(NAPAKA, "ni uspelo pridobiti sedanjosti.");
returnstatus = 3;
goto rtv_zivo_izpolni_returncleanly;
} else {
RTV_NAPISI(HROSC, "sedanjost je %u", m->sedanjost);
}
rtv_zivo_izpolni_returncleanly:
RTV_FREE(temp);
fclose(odgstream);
free(odg);
odg = NULL;
return returnstatus;
#pragma GCC diagnostic pop
}
int main (int argc, char ** argv) {
if (argc < 1+1) {
fprintf(stderr, "preberi README.md pred uporabo programa, saj vsebuje navodila in ostalo.\n");
fprintf(stderr, "preberi README.md pred uporabo programa, saj vsebuje"
"navodila in ostalo.\n");
return 1;
}
struct meta_oddaja * m = meta_oddaja_alloc();
char fn[69]; /* <id>.txt / <id>.mp4 - NE USER INPUT */
struct rtv_zivo_meta * z = rtv_zivo_meta_alloc();
char fn[420]; /* <id>.txt / <id>.mp4 - NE USER INPUT */
char * e; /* char pointer for the memes */
FILE * fd;
unsigned int i;
DIR * dir;
unsigned short int returnstatus = 0;
if (RTV_URL != NULL) {
m->id = atoi(RTV_URL);
if (strrchr(RTV_URL, '/') != NULL)
m->id = atoi(strrchr(RTV_URL, '/')+1);
if (m->id <= 0) {
fprintf(stderr, "IDja oddaje ni uspelo dobiti. preverite vnos.\n");
returnstatus = 3;
goto returncleanly;
}
} else {
m->id = RTV_TEST_ID;
switch (RTV_NACIN[0]) {
case 'O': /* za vse, kar potrebuje ID oddaje, nastavimo ID oddaje */
case 'o':
case 'M':
case 'm':
case 'T':
case 't':
case 'p':
case 'P':
case 's':
case 'S':
RTV_NAPISI(HROSC, "Ta način potrebuje ID oddaje, sedaj ga nastavljam.");
if (RTV_URL != NULL) {
m->id = atoi(RTV_URL);
if (strrchr(RTV_URL, '/') != NULL)
m->id = atoi(strrchr(RTV_URL, '/')+1);
if (m->id <= 0) {
fprintf(stderr, "IDja oddaje ni uspelo dobiti. preverite vnos.\n");
returnstatus = 3;
goto returncleanly;
}
} else {
m->id = RTV_TEST_ID;
}
break;
}
switch (RTV_NACIN[0]) {
case 'T':
@ -466,9 +646,11 @@ int main (int argc, char ** argv) {
returnstatus = 5;
goto returncleanly;
}
if (http_get(m->posnetek_url, fd) == 0) {
if (RTV_HTTP_SUCCESS(http_get(m->posnetek_url, fd))) {
fclose(fd);
RTV_NAPISI(INFO, "uspešno shranjeno.");
} else {
fclose(fd);
RTV_NAPISI(NAPAKA, "Nekaj je spodletelo pri http_get()");
returnstatus = 6;
}
@ -496,13 +678,14 @@ int main (int argc, char ** argv) {
"dolzina: %u\njwt: %s\ntip_oddaje_ime: %s\nprogram: %s\n"
"objavljeno: %s\ntip_posnetka: %s\nslicica: %s\npredvajano: %s\n"
/* "velikost: %llu\n" */ "get_meta_url: %s\nget_media_url: %s\n"
"predvajalnik_url: %s\nposnetek_url: %s\n", m->id, m->naslov,
m->tip_oddaje_id, m->zanri, m->opis, m->dolzina, m->jwt,
m->tip_oddaje_ime, m->program, m->objavljeno,
"predvajalnik_url: %s\nposnetek_url: %s\npodnapisi_url: %s\n",
m->id, m->naslov, m->tip_oddaje_id, m->zanri, m->opis, m->dolzina,
m->jwt, m->tip_oddaje_ime, m->program, m->objavljeno,
m->tip_posnetka == RTV_VIDEO_TIP ? "RTV_VIDEO_TIP" : \
m->tip_posnetka == RTV_AUDIO_TIP ? "RTV_AUDIO_TIP":"RTV_NEPOZNAN_TIP",
m->slicica, m->predvajano, /* m->velikost, */ m->get_meta_url,
m->get_media_url, m->predvajalnik_url, m->posnetek_url);
m->get_media_url, m->predvajalnik_url, m->posnetek_url,
m->podnapisi_url);
fclose(fd);
break;
case 's': /* sličica - prenese sličico oddaje */
@ -524,26 +707,103 @@ int main (int argc, char ** argv) {
returnstatus = 5;
goto returncleanly;
}
if (http_get(m->slicica, fd) == 0) {
if (RTV_HTTP_SUCCESS(http_get(m->slicica, fd))) {
fclose(fd);
RTV_NAPISI(INFO, "uspešno shranjeno.");
} else {
fclose(fd);
RTV_NAPISI(NAPAKA, "Nekaj je spodletelo pri http_get()");
returnstatus = 6;
}
break;
case 'p': /* podnapisi */ /* F za Gašperja Tiča, voditelja otroške oddaje */
case 'P': /* Iz popotne torbe, ki je uporabljena kot primer v README.md */
if (rtv_meta_izpolni(m) != 0) {
RTV_NAPISI(NAPAKA, "Ni uspelo pridobiti metapodatkov oddaje.");
returnstatus = 4;
goto returncleanly;
}
if (argc < 4) {
e = strrchr(m->podnapisi_url, '.');
snprintf(fn, sizeof(fn), "%u%s", m->id, e);
fd = fopen(fn, "w");
} else {
fd = fopen(argv[3], "w");
}
if (fd == NULL) {
RTV_NAPISI(NAPAKA, "Ni uspelo odpreti datoteke za pisanje vanjo.");
returnstatus = 5;
goto returncleanly;
}
if (RTV_HTTP_SUCCESS(http_get(m->podnapisi_url, fd))) {
fclose(fd);
RTV_NAPISI(INFO, "uspešno shranjeno.");
} else {
fclose(fd);
RTV_NAPISI(NAPAKA, "Nekaj je spodletelo pri http_get()");
returnstatus = 6;
}
break;
case 'z': /* zivo */
case 'Z':
case 0xC5: /* živo / Živo, ž = 0xc5be, Ž = 0xc5bd, tudi šivo dela! */
RTV_NAPISI(NAPAKA, "pretakanje v živo še ni izdelano!");
case RTV_ZCARON: /* živo / Živo, ž = 0xc5be, Ž = 0xc5bd, tudi šivo dela! */
if (argc <= 2) {
strcpy(z->program, "slo1");
} else {
strncpy(z->program, RTV_URL, RTV_ZIVO_PROGRAM_SIZEOF);
}
z->preteklost = argc > 4 ? atoi(argv[4]) : 9999999;
z->prihodnost = argc > 5 ? atoi(argv[5]) : 9999999;
e = argc > 3 ? argv[3] : z->program; /* dirEktorij */
dir = opendir(e);
if (dir) {
closedir(dir); /* direktorij obstaja, hvala */
} else if (errno == ENOENT) {
if (mkdir(e, 0755) != 0) {
RTV_NAPISI(NAPAKA, "med izdelavo direktorija: %s", strerror(errno));
}
} else {
RTV_NAPISI(NAPAKA, "med iskanjem direktorija: %s",
strerror(errno));
returnstatus = 5;
goto returncleanly;
}
if (rtv_zivo_izpolni(z) != 0) {
RTV_NAPISI(NAPAKA, "Ni uspelo pridobiti metapodatkov pretoka.");
returnstatus = 4;
}
for (i = z->sedanjost; i >= 0; i--) {
snprintf(fn, sizeof(fn), "%s/%u%s",
e, i, strrchr(z->kos_format, '.')); /* printf je NULL safe */
fd = fopen(fn, "w");
snprintf(fn, sizeof(fn), z->kos_format, i);
if (!RTV_HTTP_SUCCESS(http_get(fn, fd))) { /* napaka je verjetno 404 */
i--;
RTV_NAPISI(INFO, "ni več kosov v preteklosti");
fclose(fd);
break;
}
RTV_NAPISI(INFO, "prenesel kos %u iz preteklosti", i);
fclose(fd);
}
snprintf(fn, sizeof(fn), "%s/seznam_predvajanja.m3u8", e);
fd = fopen(fn, "w");
fprintf(fd, "# generirano z rtv4d-dl " RTV_VER "\n");
for (i = i; i <= z->sedanjost; i++) {
fprintf(fd, "%u%s\n", i, strrchr(z->kos_format, '.'));
}
break;
default:
fprintf(stderr, "opcija ne obstaja! poskusi test.\n");
RTV_NAPISI(NAPAKA, "opcija (%c/%u) ne obstaja!",
RTV_NACIN[0], RTV_NACIN[0]);
returnstatus = 2;
goto returncleanly;
break;
}
returncleanly:
meta_oddaja_free(m);
m = NULL;
meta_oddaja_free(m); m = NULL;
rtv_zivo_meta_free(z); z = NULL;
return returnstatus;
}
/* VODILO ZA 80 znakovno omejitev - konec sledečega komentarja je 80. znak: */
/* 4567890 (2)01234567890 (4)01234567890 (6)01234567890 */

9
test.c

@ -2,8 +2,13 @@
#include <stdlib.h>
#include <string.h>
int main (int argc, char ** argv) {
char * metavalues[] = { "abc", "def", "ghi", "jkl" };
fprintf(stdout, "%s\n", { "a", "b", "c", "d" }[3]);
char aaa[] = "chunk_1234.ts";
char bbb[] = "chunk_%u.ts";
unsigned int ccc;
sscanf(aaa, bbb, &ccc);
fprintf(stdout, "%u\n", ccc);
// char * metavalues[] = { "abc", "def", "ghi", "jkl" };
// fprintf(stdout, "%s\n", { "a", "b", "c", "d" }[3]);
// const char b[5] = "aaaaa";
// const char a[5] = "aaaaa";
// fprintf(stdout, "%d\n", strncasecmp(a, b, 325432));

Loading…
Cancel
Save