/************************************************************************* * Copyright 2009/2010/2011 Ralph Spitzner (rasp@spitzner.org) * * This file is part of v2Yahdr. * * Yahdr 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 3 of the License, or * (at your option) any later version. * * v2Yahdr 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 v2Yahdr. If not, see . **************************************************************************/ #include "ydefs.h" /* httpd - _very_ simple http server. listen -> accept -> do something -> close/die */ static int sockfd ,newsockfd, clilen; static struct sockaddr_in serv_addr,cli_addr; static uint8_t nadap; static int pipe_fd[2]; static volatile uint8_t watching; /** two yucky globals, no need for mutex here these get set by telldvr() (messages would pile up) **/ volatile uint16_t pids[10]; volatile uint8_t cdvr; static ADAPTER *adp; void pfeife(int sig) { printf("Pfeife zerbrochen\n"); } static int opendvr(int num) { int dvr_fd; char buffer[255]; sprintf(buffer,"/dev/dvb/adapter%d/dvr%d",num); printf("open dvr %d\n",num); dvr_fd = open(buffer,O_RDONLY); if(dvr_fd <= 0) { printf("%s :",buffer); perror("dvr open device"); return -1; } return dvr_fd; } void sync_stream(int fd) { uint16_t count; uint8_t c,syn,buffer[188]; //// sync stream printf("syncing\n"); count = 0; while (1) { read(fd,buffer,1); if (count++ == 188 * 300) { fprintf(stderr,"I can hardly believe this is MPEG-2 TS. (buffer[0] = %x..\n",buffer[0]&0xff); return; } c = buffer[0] & 0xff; syn = c == 0x47 ? 1 : 0; if (syn) { printf("c = %x\n",c); read(fd,buffer,188); printf("next = %x\n",buffer[187] & 0xff); if (buffer[187] == 0x47) { read(fd,buffer,187); break; } } } printf("synced\n"); } void *tspipe(void *nix) { int dvr_fd, p_fd; uint8_t buffer[188]; volatile uint8_t olda; int len; olda = 255; dvr_fd = 0; adp = NULL; //keep compiler happy pipe(pipe_fd); p_fd = pipe_fd[1]; set_nonblock(p_fd); while(1) { if(watching == false) { sleep(1); continue; } if(cdvr != olda) { INFO("adapter changed %d -> %d\n",olda,cdvr); adp = adapters; while(adp) { if(adp->number == olda) { adp->watching = false; break; } adp = adp->next; } if(dvr_fd) close(dvr_fd); dvr_fd = opendvr(cdvr); adp = adapters; while(adp) { if(adp->number == cdvr) { adp->watching = true; break; } adp = adp->next; } olda = cdvr; sync_stream(dvr_fd); } else if(dvr_fd > 0 && watching == true) { len = read(dvr_fd,buffer,188); if(len != 188) { //fprintf(stderr,"##### len %d ",len); //perror(" tspipe t_read"); continue; } if (buffer[0] != 0x47) { printf("######### resync\n"); sync_stream(dvr_fd); } if(len ) { adp->watching = watching; write(p_fd,buffer,len); } else { adp->watching = watching; } } } //notreached return NULL; } static void handlereq(int fd) { char buffer[255]; uint16_t npid1; uint8_t outpid; int i, fifo_fd; int n; printf("handle video\n"); fifo_fd = pipe_fd[0]; /// get last tuned channel back on (might be untuned by epg_runner() ) if(tuned_ts.sp) { tuneto(tuned_ts.sp->name); } watching = 1; /// don't care what they want, just send header sprintf(buffer,"HTTP/1.1 200 OK\nContent-Type: video/mpeg\n\n"); write(fd,buffer,strlen(buffer)); while(1) { n = read(fifo_fd,(uint8_t *)buffer,188); if(n == -1) { break; } if(n != 188) { continue; } npid1 = (buffer[1] & 0x1f) << 8 ; npid1 |= (buffer[2] & 0xff); outpid = 0; for(i = 0; i != 8; i++) { if((npid1 != 0) && (pids[i] == npid1)) { outpid = 0x80 + i; break; } } buffer[1] &= 0xe0; buffer[2] = outpid; if(outpid != 0) { if(send(fd,buffer,188,MSG_NOSIGNAL) != 188) { //close(fifo_fd); watching = false; adp->watching = watching; perror("stream client died"); return; } } // else printf("murks\n"); } close(fifo_fd); return; } void *dvrd(void *bla) { sockfd = socket(AF_INET, SOCK_STREAM , 0); if (sockfd < 0) { printf("dvrd can't create socket\n"); return NULL ; } watching = 0; bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(DVR_PORT); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { printf("dvrd can't bind to port %d\n",DVR_PORT); return NULL; } listen(sockfd,5); clilen = sizeof(cli_addr); nadap = adapters->number; while (1) { newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen); if (newsockfd < 0) { perror("dvr ERROR on accept"); sleep(10); continue; } handlereq(newsockfd); } }