source: titan/titan/record.h @ 15272

Last change on this file since 15272 was 15189, checked in by nit, 12 years ago

[titan] extend freemenulist

File size: 25.9 KB
Line 
1#ifndef RECORD_H
2#define RECORD_H
3
4int recordcheckcrypt(struct dvbdev* fenode, int servicetype)
5{
6        struct service* servicenode = service;
7
8        while(servicenode != NULL)
9        {
10                if(fenode == servicenode->fedev && servicenode->channel != NULL && servicenode->channel->crypt > 0)
11                {
12                        if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER) return 1;
13                        if(servicetype == RECORDSTREAM && servicenode->type == RECORDTIMESHIFT) return 1;
14                        if(servicetype == CHANNEL && servicenode->type == RECORDTIMESHIFT) return 1;
15                }
16                servicenode = servicenode->next;
17        }
18        return 0;
19}
20
21//flag bit 0 = with timeout
22//flag bit 1 = show textbox
23//flag bit 2 = print debug
24//flag bit 3 = return text
25char* recordcheckret(struct stimerthread* timernode, int ret, int flag)
26{
27        char* tmpstr = NULL;
28        int timeout = 0;
29        if(checkbit(flag, 0) == 1)
30                timeout = 10;
31
32        if(ret != 0)
33        {
34                switch(ret)
35                {
36                        case 1:
37                                tmpstr = ostrcat(_("HDD not configured\ncan't find record path"), "", 0, 0);
38                                break;
39                        case 2:
40                                tmpstr = ostrcat(_("Not enought space"), "", 0, 0);
41                                break;
42                        case 3:
43                                tmpstr = ostrcat(_("Error create filename"), "", 0, 0);
44                                break;
45                        case 4:
46                                tmpstr = ostrcat(_("Can't open file"), "", 0, 0);
47                                break;
48                        case 5:
49                                tmpstr = ostrcat(_("Can't open FRONTEND device"), "", 0, 0);
50                                break;
51                        case 6:
52                                tmpstr = ostrcat(_("Can't open DMX device"), "", 0, 0);
53                                break;
54                        case 7:
55                                tmpstr = ostrcat(_("Pid's not ok"), "", 0, 0);
56                                break;
57                        case 8:
58                                tmpstr = ostrcat(_("Channel or Transponder is empty"), "", 0, 0);
59                                break;
60                        case 9:
61                                tmpstr = ostrcat(_("Write error"), "", 0, 0);
62                                break;
63                        case 10:
64                                tmpstr = ostrcat(_("No memory"), "", 0, 0);
65                                break;
66                        case 11:
67                                tmpstr = ostrcat(_("Failed open split file"), "", 0, 0);
68                                break;
69                        case 12:
70                                tmpstr = ostrcat(_("Frontend type unknown"), "", 0, 0);
71                                break;
72                        case 13:
73                                tmpstr = ostrcat(_("Tune to channel failed"), "", 0, 0);
74                                break;
75                        case 14:
76                                break;
77                        case 15:
78                                tmpstr = ostrcat(_("To many read error or end of file"), "", 0, 0);
79                                break;
80                        case 16:
81                                tmpstr = ostrcat(_("Can't create service"), "", 0, 0);
82                                break;
83                }
84                if(tmpstr != NULL)
85                {
86                        if(checkbit(flag, 2) == 1) err("%s", tmpstr);
87                        if(checkbit(flag, 1) == 1) textbox(_("Record / Timeshift / Stream"), tmpstr, _("EXIT"), getrcconfigint("rcexit", NULL), NULL, 0, NULL, 0, NULL, 0, 600, 200, timeout, 0);
88                }
89        }
90        if(checkbit(flag, 3) == 0)
91        {
92                free(tmpstr);
93                tmpstr = NULL;
94        }
95        return tmpstr;
96}
97
98void recordwriteepg(char* filename, struct channel* chnode, struct rectimer* rectimernode)
99{
100        struct epg* epgnode = NULL;
101        FILE *fd = NULL;
102        int ret = 0, count = 0;
103        char* tmpstr = NULL, *epgfilename = NULL, *buf = NULL;
104        struct tm *loctime = NULL;
105
106        if(filename == NULL)
107        {
108                err("epg record filename = NULL");
109                return;
110        }
111
112        epgfilename = changefilenameext(filename, ".epg");
113       
114        //check if epg is in rectimer time
115        if(rectimernode != NULL)
116        {
117                epgnode = getepgakt(chnode);
118                while(epgnode != NULL && (epgnode->starttime < rectimernode->begin || epgnode->starttime >= rectimernode->end))
119                        epgnode = epgnode->next;
120        }
121        else
122                epgnode = getepgbytime(chnode, time(NULL) + 60);
123       
124        if(epgnode != NULL)
125        {
126                fd = fopen(epgfilename, "w");
127                if(fd == NULL)
128                {
129                        perr("open %s", epgfilename);
130                        free(epgfilename);
131                        return;
132                }
133                chmod(epgfilename, 0666);
134
135                if(epgnode->title != NULL)
136                {
137                        buf = malloc(MINMALLOC);
138                        loctime = localtime(&epgnode->starttime);
139                        strftime(buf, MINMALLOC, "%d-%m-%Y %H:%M", loctime);
140                        ret += fwrite(buf, strlen(buf), 1, fd);
141                        ret += fwrite(" - ", 3, 1, fd);
142                        ret += fwrite(epgnode->title, strlen(epgnode->title), 1, fd);
143                        ret += fwrite("\n", 1, 1, fd);
144                        count += 4;
145                        free(buf); buf = NULL;
146                }
147                if(epgnode->subtitle != NULL)
148                {
149                        ret += fwrite(epgnode->subtitle, strlen(epgnode->subtitle), 1, fd);
150                        ret += fwrite("\n\n", 2, 1, fd);
151                        count += 2;
152                }
153                if(epgnode->desc != NULL)
154                {
155                        tmpstr = epgdescunzip(epgnode);
156                        if(tmpstr != NULL)
157                        {
158                                ret += fwrite(tmpstr, strlen(tmpstr), 1, fd);
159                                count++;
160                                free(tmpstr); tmpstr = NULL;
161                        }
162                }
163
164                if(ret != count)
165                {
166                        err("writting record epg file");
167                }
168
169                fclose(fd);
170        }
171        free(epgfilename);
172}
173
174void recordstop(struct service* node)
175{
176        debug(1000, "in");
177        struct rectimer* rectimernode = NULL;
178        int afterevent = 1, type = -1;
179
180        if(node != NULL)
181        {
182                type = node->type;
183
184                if(node->fedev != NULL && node->type != RECORDTIMESHIFT)
185                        node->fedev->felock--;
186
187                m_lock(&status.rectimermutex, 1);
188                rectimernode = getrectimerbyservice(node);
189                if(rectimernode != NULL)
190                        afterevent = rectimernode->afterevent;
191                m_unlock(&status.rectimermutex, 1);
192               
193                delservice(node, 0);
194
195                if(type == RECORDSTREAM)
196                        status.streaming--;
197                else if(type == RECORDTIMESHIFT)
198                        status.timeshift = 0;
199                else if(type == RECORDPLAY)
200                        status.playing = 0;
201                else
202                        status.recording--;
203
204                deltranspondertunablestatus();
205
206                //afterevent: 0 = auto
207                //afterevent: 1 = nothing
208                //afterevent: 2 = standby
209                //afterevent: 3 = poweroff
210                if(afterevent == 0)
211                {
212                        if(status.startmode == 1) afterevent = 2;
213                        else if(getwaswakuptimer() == 1) afterevent = 3;
214
215                }
216                if(afterevent == 2 && status.standby == 0)
217                {
218                        status.standby = 2;
219                        screenstandby();
220                }
221                if(afterevent == 3)
222                {
223                        if(status.recording < 1)
224                                oshutdown(1, 3);
225                }
226        }
227
228        debug(1000, "out");
229}
230
231int recordsplit(struct service* servicenode)
232{
233        int ret = 0;
234        char* filename = NULL;
235
236        filename = malloc(256);
237        if(filename == NULL)
238        {
239                err("no mem");
240                ret = 10;
241                servicenode->recendtime = 1;
242        }
243        else
244        {
245                fdatasync(servicenode->recdstfd);
246                close(servicenode->recdstfd);
247                servicenode->rectotal = 0;
248                servicenode->reclastsync = 0;
249
250                if(servicenode->reccount < 2)
251                {
252                        if(strlen(servicenode->recname) > 3)
253                                servicenode->recname[strlen(servicenode->recname) - 3] = '\0';
254                }
255                else
256                {
257                        if(strlen(servicenode->recname) > 7)
258                                servicenode->recname[strlen(servicenode->recname) - 7] = '\0';
259                }
260                snprintf(filename, 255, "%s.%03d.ts", servicenode->recname, servicenode->reccount++);
261                free(servicenode->recname);
262                servicenode->recname = filename;
263
264                debug(250, "split record file - Recording to %s...", filename);
265
266                servicenode->recdstfd = open(filename, O_WRONLY|O_CREAT|O_LARGEFILE, 0644);
267                if(servicenode->recdstfd < 0)
268                {
269                        debug(250, "split record file - can't open recording file!");
270                        ret = 11;
271                        servicenode->recendtime = 1;
272                }
273                else
274                        posix_fadvise(servicenode->recdstfd, 0, 0, POSIX_FADV_RANDOM);
275        }
276        return ret;
277}
278
279int readwritethread(struct stimerthread* stimer, struct service* servicenode, int flag)
280{
281        int readret = 0, writeret = 0, ret = 0, recbsize = 0, tmprecbsize = 0, i = 0, pktcount = 0;
282        int readtimeout = -1, writetimeout = -1;
283        unsigned char* buf = NULL, *tmpbuf = NULL;
284        char* retstr = NULL;
285        //off64_t pos = 0;
286
287        debug(250, "start read-write thread");
288
289        if(servicenode == NULL)
290        {
291                err("servicenode = NULL");
292                return 1;
293        }
294
295        if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
296        {
297                recbsize = servicenode->tssize * 2788;
298                readtimeout = 5000000;
299                writetimeout = 5000000; //5 sec
300        }
301               
302        if(servicenode->type == RECORDPLAY || servicenode->type == RECORDSTREAM)
303        {
304                if(servicenode->recdstfd < 0)
305                {
306                        err("destination fd not ok")
307                        return 1;
308                }
309                if(servicenode->type == RECORDPLAY)
310                {
311                        recbsize = servicenode->tssize * 512;
312                        tmprecbsize = 188 * 512;
313                }
314                if(servicenode->type == RECORDSTREAM) recbsize = servicenode->tssize * 2788;
315                readtimeout = 5000000;
316                writetimeout = 5000000;
317        }
318       
319#ifdef SIMULATE
320        int fd = open("simulate/record.ts", O_RDONLY | O_LARGEFILE);
321        if(fd < 0)
322        {
323                perr("open simulate/record.ts");
324                return 1;
325        }
326#endif
327
328        buf = malloc(recbsize);
329        if(buf == NULL)
330        {
331                err("no mem");
332                return 1;
333        }
334       
335        if(servicenode->type == RECORDPLAY && servicenode->tssize == 192)
336        {
337                tmpbuf = malloc(tmprecbsize);
338                if(tmpbuf == NULL)
339                {
340                        err("no mem");
341                        return 1;
342                }
343        }
344       
345        if(servicenode->recdmxstart == 0)
346        {
347                dmxstart(servicenode->dmxvideodev);
348                servicenode->recdmxstart = 1;
349        }
350       
351        while(1)
352        {       
353#ifdef SIMULATE
354                servicenode->recsrcfd = fd;
355                readret = dvbreadfd(servicenode->recsrcfd, buf, 0, recbsize, readtimeout);
356                usleep(1000);
357#else
358                if(servicenode->type == RECORDPLAY)
359                        m_lock(&status.tsseekmutex, 15);
360                readret = dvbreadfd(servicenode->recsrcfd, buf, 0, recbsize, readtimeout);
361                if(servicenode->type == RECORDPLAY)
362                        m_unlock(&status.tsseekmutex, 15);
363#endif
364                if(readret > 0)
365                {
366//repeatewrite:
367                        if(servicenode->type == RECORDSTREAM)
368                                writeret = sockwrite(servicenode->recdstfd, buf, readret, writetimeout);
369                        else
370                        {
371                                if(servicenode->type == RECORDPLAY && servicenode->tssize == 192)
372                                {
373                                        // remove 4 bytes per paket from mts and m2ts streams
374                                        pktcount = readret / 192;
375                                        for(i = 0; i < pktcount; i++)
376                                                memcpy(tmpbuf + (i * 188), buf + (i * 192) + 4, 188);
377                                        writeret = dvbwrite(servicenode->recdstfd, tmpbuf, pktcount * 188, writetimeout);
378                                        writeret = writeret + (pktcount * 4);
379                                }
380                                else
381                                        writeret = dvbwrite(servicenode->recdstfd, buf, readret, writetimeout);
382                        }
383                        //else if(servicenode->type == RECORDPLAY)
384                        //      writeret = dvbwrite(servicenode->recdstfd, buf, readret, writetimeout);
385                        //else if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
386                        //      writeret = write(servicenode->recdstfd, buf, readret);
387
388                        if(writeret < 1)
389                        {
390                                //if((servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT) && (errno == EINTR || errno == EAGAIN || errno == EBUSY))
391                                //{
392                                //      perr("record/ts write repeate");
393                                //      goto repeatewrite;
394                                //}
395                                ret = 9;
396                                servicenode->recendtime = 1;
397                        }
398                        else if(readret != writeret)
399                        {
400                                debug(250, "not all data written read=%d, written=%d", readret, writeret);
401                        }
402
403                        if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
404                        {
405                                //sync
406                                servicenode->reclastsync += writeret;
407                                if(servicenode->reclastsync > 524288)
408                                {
409                                        int tosync = servicenode->reclastsync > 2097152 ? 2097152 : servicenode->reclastsync &~ 4095; //sync max 2MB
410                                        //pos = lseek64(servicenode->recdstfd, 0, SEEK_CUR);
411                                        //pos -= tosync;
412                                        //posix_fadvise64(servicenode->recdstfd, pos, tosync, POSIX_FADV_DONTNEED);
413                                        servicenode->reclastsync -= tosync;
414
415                                        //split only after sync
416                                        if(status.recsplitsize && servicenode->type != RECORDTIMESHIFT)
417                                        {
418                                                servicenode->rectotal += tosync;
419                                                if(servicenode->rectotal > status.recsplitsize)
420                                                ret = recordsplit(servicenode);
421                                        }
422                                }
423                        }
424                }
425                else if(readret <= 0)
426                {
427                        ret = 15;
428                        servicenode->recendtime = 1;
429                        if(readret < -1)
430                                perr("read");
431                }
432
433                if(servicenode->recendtime != 0 && (servicenode->recendtime) < time(NULL))
434                {
435                        if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
436                                fdatasync(servicenode->recdstfd);
437                        if(ret != 0) // error
438                        {
439                                if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
440                                        addtimer(&recordcheckret, START, 1000, 1, (void*)ret, (void*)3, NULL);
441                                retstr = recordcheckret(NULL, ret, 12);
442
443                                //if(servicenode->type == RECORDSTREAM)
444                                //      sockwrite(servicenode->recdstfd, (unsigned char*)retstr, strlen(retstr), -1);
445                                if(servicenode->type == RECORDTIMER)
446                                {
447                                        m_lock(&status.rectimermutex, 1);
448                                        struct rectimer* rectimernode = getrectimerbyservice(servicenode);
449                                        if(rectimernode != NULL)
450                                        {
451                                                rectimernode->status = 3;
452                                                free(rectimernode->errstr);
453                                                rectimernode->errstr = ostrcat(retstr, "", 0, 0);
454                                                status.writerectimer = 1;
455                                                writerectimer(getconfig("rectimerfile", NULL), 1);
456                                        }
457                                        m_unlock(&status.rectimermutex, 1);
458                                }
459                                free(retstr); retstr = NULL;
460                        }
461                        recordstop(servicenode);
462                        break;
463                }
464        }
465
466#ifdef SIMULATE
467        close(fd);
468#endif
469        if(buf != NULL) free(buf);
470        if(tmpbuf != NULL) free(tmpbuf);
471        debug(250, "stop read-write thread");
472        return 0;
473}
474
475char* recordcreatefilename(char* path, char* channelname, char* moviename, int type)
476{
477        time_t sec;
478        struct tm *loctime;
479        char *buf = NULL, *buf1 = NULL;
480        char* tmpstr = NULL;
481
482        if(path == NULL)
483                return NULL;
484
485        tmpstr = ostrcat(path, "/", 0, 0);
486        if(type != RECTIMESHIFT)
487        {
488                if(channelname == NULL || strlen(channelname) == 0)
489                        tmpstr = ostrcat(tmpstr, "unknown", 1, 0);
490                else
491                        tmpstr = ostrcat(tmpstr, channelname, 1, 0);
492                tmpstr = ostrcat(tmpstr, "-", 1, 0);
493        }
494        if(moviename == NULL || strlen(moviename) == 0)
495                tmpstr = ostrcat(tmpstr, "unknown", 1, 0);
496        else
497                tmpstr = ostrcat(tmpstr, moviename, 1, 0);
498
499        sec = time(NULL);
500        loctime = localtime(&sec);
501
502        buf = malloc(MINMALLOC);
503        if(buf == NULL)
504        {
505                err("no memory");
506                return NULL;
507        }
508
509        strftime(buf, MINMALLOC, "%Y%m%d%H%M%S", loctime);
510        buf1 = ostrcat(buf, "", 1, 0);
511
512        tmpstr = ostrcat(tmpstr, "-", 1, 0);
513        tmpstr = ostrcat(tmpstr, buf1, 1, 1);
514        tmpstr = ostrcat(tmpstr, ".ts", 1, 0);
515
516        debug(1000, "out");
517        return tmpstr;
518}
519
520int recordstartreal(struct channel* chnode, int filefd, int recordfd, int type, time_t endtime, struct rectimer* rectimernode, int tssize)
521{
522        int ret = 0, fd = -1, servicetype = RECORDDIRECT, festatus = 0;
523        char* path = NULL, *chname = NULL, *filename = NULL, *moviename = NULL;
524        unsigned char* patbuf = NULL, *pmtbuf = NULL;
525        struct epg* epgnode = NULL;
526        struct service* servicenode = NULL;
527        struct dvbdev* fenode = NULL, *dmxnode = NULL;
528        struct audiotrack* atrack = NULL;
529        char* tmpstr = NULL;
530        struct transponder* tpnode = NULL;
531        int input = DMX_IN_FRONTEND;
532
533        if(chnode == NULL && filefd < 0)
534        {
535                ret = 8;
536                goto end;
537        }
538
539        if(filefd < 0)
540        {
541                tpnode = chnode->transponder;
542                if(tpnode == NULL)
543                {
544                        ret = 8;
545                        goto end;
546                }
547        }
548
549        switch(type)
550        {
551                case RECPLAY:
552                        servicetype = RECORDPLAY;
553                        fd = recordfd;
554                        break;
555                case RECSTREAM:
556                        servicetype = RECORDSTREAM;
557                        fd = recordfd;
558                        break;
559                case RECTIMESHIFT:
560                        servicetype = RECORDTIMESHIFT;
561                        path = getconfig("rec_timeshiftpath", NULL);
562                        moviename = "timeshift";
563                        break;
564                case RECTIMER:
565                        servicetype = RECORDTIMER;
566                        if(rectimernode != NULL && rectimernode->recpath != NULL)
567                                path = rectimernode->recpath;
568                        else
569                                path = getconfig("rec_timerpath", NULL);
570                        if(chnode != NULL)
571                        {
572                                chname = strstrip(chnode->name);
573                                delspezchar(chname, 1);
574                        }
575                        moviename = strstrip(rectimernode->name);
576                        delspezchar(moviename, 1);
577                        break;
578                default:
579                        servicetype = RECORDDIRECT;
580                        path = getconfig("rec_path", NULL);
581                        if(chnode != NULL)
582                        {
583                                chname = strstrip(chnode->name);
584                                delspezchar(chname, 1);
585                        }
586                        epgnode = getepgbytime(status.aktservice->channel, time(NULL) + 60);
587                        if(epgnode != NULL)
588                        {
589                                moviename = strstrip(epgnode->title);
590                                delspezchar(moviename, 1);
591                        }
592                        break;
593        }
594
595        if(type != RECSTREAM && type != RECPLAY)
596        {
597                if(!isdir(path))
598                {
599                        ret = 1;
600                        goto end;
601                }
602
603                //check HDD free space
604                //deaktivate, on my 500GB FAT32 HDD, this takes mor then 10 min
605/*
606                if(getfreespace(path) < getconfigint("recordfreespace", NULL) * 1024 * 1024)
607                {
608                        ret = 2;
609                        goto end;
610                }
611*/
612
613                filename = recordcreatefilename(path, chname, moviename, type);
614                if(filename == NULL)
615                {
616                        ret = 3;
617                        goto end;
618                }
619
620                fd = open(filename, O_WRONLY | O_CREAT | O_LARGEFILE, 0666);
621                if(fd < 0)
622                {
623                        char* fn = strrchr(filename, '/');
624                        if(fn == NULL)
625                                delspezchar(filename, 0);
626                        else
627                                delspezchar(fn + 1, 0);
628       
629                        fd = open(filename, O_WRONLY|O_CREAT|O_LARGEFILE, 0666);
630                        if(fd < 0)
631                        {
632                                ret = 4;
633                                goto end;
634                        }
635                }
636                posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM); //turn off kernel cache
637        }
638
639        servicenode = addservice(NULL);
640        if(servicenode == NULL)
641        {
642                ret = 16;
643                goto end;
644        }
645        servicenode->tssize = tssize;
646        servicenode->recdstfd = fd;
647        servicenode->channel = chnode;
648        servicenode->transponder = tpnode;
649
650        if(filefd < 0)
651        {
652                //got frontend dev
653                fenode = fegetfree(tpnode, 2, NULL);
654                if(fenode == NULL)
655                {
656                        if(type == RECSTREAM)
657                        {
658                                ret = 5;
659                                goto end;
660                        }
661                        else
662                        {
663                                if(textbox(_("Message"), _("Can't find free Tuner for Record.\nSwitch to Recording/Timeshift Channel ?"), _("EXIT"), getrcconfigint("rcexit", NULL), _("OK"), getrcconfigint("rcok", NULL), NULL, 0, NULL, 0, 600, 200, 10, 0) == 1)
664                                {
665                                        ret = 14;
666                                        goto end;
667                                }
668                                else
669                                {
670                                        if(rectimernode != NULL)
671                                                servicestart(chnode, rectimernode->channellist, rectimernode->pincode, 0);
672                                        else
673                                                servicestart(chnode, NULL, NULL, 0);
674                                       
675                                        if(status.standby > 0) servicestop(status.aktservice, 1, 0);   
676                                       
677                                        fenode = fegetfree(tpnode, 2, NULL);
678                                        if(fenode == NULL)
679                                        {
680                                                ret = 5;
681                                                goto end;
682                                        }
683                                }
684                        }
685                }
686                if(type != RECTIMESHIFT) fenode->felock++;
687
688                //frontend tune
689                if(fenode != status.aktservice->fedev || (status.standby > 0 && getconfigint("standbytuneroff", NULL) == 1))
690                {
691                        if(fenode->feinfo->type == FE_QPSK)
692                        {
693                                feset(fenode, tpnode);
694                                fetunedvbs(fenode, tpnode);
695                        }
696                        else if(fenode->feinfo->type == FE_QAM)
697                                fetunedvbc(fenode, tpnode);
698                        else if(fenode->feinfo->type == FE_OFDM)
699                                fetunedvbt(fenode, tpnode);
700                        else
701                        {
702                                ret = 12;
703                                if(type != RECTIMESHIFT) fenode->felock--;
704                                goto end;
705                        }
706
707                        festatus = fewait(fenode);
708                        if(debug_level == 200) fereadstatus(fenode);
709                        if(festatus != 0)
710                        {
711                                ret = 13;
712                                if(type != RECTIMESHIFT) fenode->felock--;
713                                goto end;
714                        }
715                }
716
717                servicenode->fedev = fenode;
718
719                //demux  start
720                dmxnode = dmxopen(fenode);
721                if(dmxnode != NULL && dmxnode->fd >= 0)
722                {
723                        servicenode->recsrcfd = dmxnode->fd;
724                        if(type == RECTIMESHIFT)
725                                dmxsetbuffersize(dmxnode, getconfigint("dmxtimeshiftbuffersize", NULL));
726                        else if(type == RECSTREAM)
727                                dmxsetbuffersize(dmxnode, getconfigint("dmxstreambuffersize", NULL));
728                        else
729                                dmxsetbuffersize(dmxnode, getconfigint("dmxrecordbuffersize", NULL));
730                        servicenode->dmxaudiodev = dmxnode;
731                        servicenode->dmxvideodev = dmxnode;
732                        dmxsetsource(dmxnode, fenode->fedmxsource);
733#if DVB_API_VERSION > 3
734                        dmxsetpesfilter(dmxnode, 0, input, DMX_OUT_TSDEMUX_TAP, DMX_PES_OTHER, 1);
735#else
736                        dmxsetpesfilter(dmxnode, 0, input, DMX_OUT_TAP, 0, 1);
737#endif
738                        patbuf = dvbgetpat(fenode, -1);
739                        chnode->pmtpid = dvbgetpmtpid(patbuf, chnode->serviceid);
740
741                        m_lock(&status.servicemutex, 2);
742                        if(status.aktservice->channel != chnode)
743                        {
744                                //reset channel info
745                                serviceresetchannelinfo(chnode);
746                                pmtbuf = dvbgetpmt(fenode, patbuf, chnode->serviceid, &chnode->pmtpid, NULL, -1, 0);
747                                dvbgetinfo(pmtbuf, chnode);
748                        }
749                        if(status.pmtmode == 1)
750                        {
751                                if(recordcheckcrypt(fenode, servicetype) == 0)
752                                        dvbwritepmt(servicenode, pmtbuf);
753                                else
754                                        debug(250, "don't write pmt.tmp, another crypt channel use this frontend");
755                        }
756                        else
757                                sendcapmt(servicenode, 0, 3);
758                        m_unlock(&status.servicemutex, 2);
759
760                        free(pmtbuf); pmtbuf = NULL;
761                        free(patbuf); patbuf = NULL;
762                        if((chnode->audiopid < 1 && chnode->videopid < 1) || chnode->pmtpid < 1)
763                        {
764#ifndef SIMULATE
765                                ret = 7;
766                                if(type != RECTIMESHIFT) fenode->felock--;
767                                goto end;
768#endif
769                        }
770                        if(chnode->audiopid > 0) dmxaddpid(dmxnode, chnode->audiopid);
771                        if(chnode->videopid > 0) dmxaddpid(dmxnode, chnode->videopid);
772                        dmxaddpid(dmxnode, chnode->pmtpid);
773                        //dmxaddpid(dmxnode, chnode->pcrpid);
774                        //add all audiotracks
775                        atrack = chnode->audiotrack;
776                        while(atrack != NULL)
777                        {
778                                if(atrack->audiopid > 0 && atrack->audiopid != chnode->audiopid)
779                                        dmxaddpid(dmxnode, atrack->audiopid);
780                                atrack = atrack->next;
781                        }
782                }
783                else
784                {
785                        ret = 6;
786                        if(type != RECTIMESHIFT) fenode->felock--;
787                        goto end;
788                }
789        }
790
791        if(rectimernode != NULL)
792                rectimernode->servicenode = servicenode;
793
794        servicenode->recendtime = endtime;
795        servicenode->reccount = 1;
796        servicenode->type = servicetype;
797
798        if(filefd < 0)
799                deltranspondertunablestatus();
800        else
801                servicenode->recsrcfd = filefd;
802
803        if(type == RECSTREAM)
804        {
805                status.streaming++;
806                servicenode->recname = ostrcat("stream ", oitoa(recordfd), 0, 1);
807        }
808        else if(type == RECTIMESHIFT)
809        {
810                status.timeshift = 1;
811                servicenode->recname = ostrcat(filename, "", 0, 0);
812        }
813        else if(type == RECPLAY)
814        {
815                status.playing = 1;
816                servicenode->recdmxstart = 1;
817        }
818        else if(type == RECDIRECT || type == RECTIMER)
819        {
820                status.recording++;
821                servicenode->recname = ostrcat(filename, "", 0, 0);
822        }
823
824        if(type != RECSTREAM && type != RECTIMESHIFT && type != RECPLAY)
825                recordwriteepg(filename, chnode, rectimernode);
826        if(type == RECTIMER)
827        {
828                tmpstr = ostrcat(_("Timer Record start !\n"), filename, 0, 0);
829                textbox(_("Message"), tmpstr, _("EXIT"), getrcconfigint("rcexit", NULL), NULL, 0, NULL, 0, NULL, 0, 600, 200, 4, 0);
830                free(tmpstr); tmpstr = NULL;
831        }
832       
833        //start readwrite thread
834        addtimer(&readwritethread, START, 1000, 1, (void*)servicenode, NULL, NULL);
835       
836        if(filename != NULL) debug(250, "rec filename = %s\n", filename);
837
838end:
839        if(ret > 0)
840        {
841                delservice(servicenode, 1);
842                if(filename != NULL) unlink(filename);
843        }
844        free(filename); filename = NULL;
845        return ret;
846}
847
848int recordstart(struct channel* chnode, int filefd, int recordfd, int type, time_t endtime, struct rectimer* rectimernode)
849{
850        return recordstartreal(chnode, filefd, recordfd, type, endtime, rectimernode, 188);
851}
852
853struct service* getrecordbyname(char* recname, int type)
854{
855        debug(1000, "in");
856        struct service* servicenode = service;
857
858        if(recname == NULL)
859        {
860                debug(1000, "out -> NULL detect");
861                return NULL;
862        }
863
864        while(servicenode != NULL)
865        {
866                if((type == -1 && (servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)) || type == servicenode->type)
867                {
868                        if(servicenode->recname != NULL)
869                        {
870                                if(strstr(recname, servicenode->recname) != NULL)
871                                        return servicenode;
872                        }
873                }
874                servicenode = servicenode->next;
875        }
876
877        return NULL;
878        debug(1000, "out");
879}
880
881int screenrecordduration(int minutes)
882{
883                int rcret = 0, ret = 0;
884                struct skin* recordduration = getscreen("recordduration");
885                char* tmpnr = NULL;
886
887                changemask(recordduration, "0000");
888                if(minutes < 0) minutes = 0;
889                if(minutes > 9999) minutes = 9999;
890                tmpnr = malloc(5);
891                snprintf(tmpnr, 5, "%04d", minutes);
892                changeinput(recordduration, tmpnr);
893                free(tmpnr);
894
895                drawscreen(recordduration, 0);
896                addscreenrc(recordduration, recordduration);
897
898                while(1)
899                {
900                        rcret = waitrc(recordduration, 0, 0);
901                        if(rcret == getrcconfigint("rcexit", NULL))
902                        {
903                                changeret(recordduration, NULL);
904                                break;
905                        }
906                        if(rcret == getrcconfigint("rcok", NULL))
907                                break;
908                }
909
910                if(recordduration->ret != NULL && ostrcmp(recordduration->ret, "0") != 0)
911                        ret = atoi(recordduration->ret);
912
913                delownerrc(recordduration);
914                clearscreen(recordduration);
915
916                return ret;
917}
918
919void screenrecordstop()
920{
921        char* tmpstr = NULL;
922        struct service* servicenode = service;
923        struct menulist* mlist = NULL, *mbox = NULL;
924
925        while(servicenode != NULL)
926        {
927                if((servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER) && servicenode->recname != NULL)
928                {
929                        tmpstr = ostrcat(tmpstr, _("stop"), 1, 0);
930                        tmpstr = ostrcat(tmpstr, " (", 1, 0);
931                        tmpstr = ostrcat(tmpstr, servicenode->recname, 1, 0);
932                        tmpstr = ostrcat(tmpstr, ")", 1, 0);
933                       
934                        addmenulist(&mlist, tmpstr, NULL, NULL, 0, 0);
935                        free(tmpstr); tmpstr = NULL;
936                }
937                servicenode = servicenode->next;
938        }
939
940        mbox = menulistbox(mlist, "recordlist", "Record", NULL, NULL, 0, 0);
941       
942        if(mbox != NULL && strstr(mbox->name, "stop") == mbox->name)
943        {
944                servicenode = getrecordbyname(mbox->name, RECORDDIRECT);
945                if(servicenode != NULL)
946                        servicenode->recendtime = 1;
947                else
948                {
949                        servicenode = getrecordbyname(mbox->name, RECORDTIMER);
950                        if(servicenode != NULL)
951                                servicenode->recendtime = 1;
952                }
953        }
954       
955        freemenulist(mlist, 1); mlist = NULL;
956}
957
958void screenrecorddirect()
959{
960        char* tmpstr = NULL;
961        int ret = 0, ret1 = 0;
962        struct service* servicenode = service;
963        struct epg* epgnode = NULL;
964        struct menulist* mlist = NULL, *mbox = NULL;
965
966        while(servicenode != NULL)
967        {
968                if(servicenode->type == RECORDDIRECT && servicenode->recname != NULL)
969                {
970                        tmpstr = ostrcat(tmpstr, _("stop"), 1, 0);
971                        tmpstr = ostrcat(tmpstr, " (", 1, 0);
972                        tmpstr = ostrcat(tmpstr, servicenode->recname, 1, 0);
973                        tmpstr = ostrcat(tmpstr, ")", 1, 0);
974                       
975                        addmenulist(&mlist, tmpstr, NULL, NULL, 0, 0);
976                        free(tmpstr); tmpstr = NULL;
977                       
978                        tmpstr = ostrcat(tmpstr, _("change"), 1, 0);
979                        tmpstr = ostrcat(tmpstr, " (", 1, 0);
980                        tmpstr = ostrcat(tmpstr, servicenode->recname, 1, 0);
981                        tmpstr = ostrcat(tmpstr, ")", 1, 0);
982                       
983                        addmenulist(&mlist, tmpstr, NULL, NULL, 0, 0);
984                        free(tmpstr); tmpstr = NULL;
985                }
986                servicenode = servicenode->next;
987        }
988
989        addmenulist(&mlist, "add recording (stop after current event)", NULL, NULL, 0, 0);
990        addmenulist(&mlist, "add recording (indefinitely)", NULL, NULL, 0, 0);
991        addmenulist(&mlist, "add recording (enter duration)", NULL, NULL, 0, 0);
992
993        mbox = menulistbox(mlist, "recordlist", "Record", NULL, NULL, 0, 0);
994       
995        if(mbox != NULL && strstr(mbox->name, "stop") == mbox->name)
996        {
997                servicenode = getrecordbyname(mbox->name, RECORDDIRECT);
998                if(servicenode != NULL)
999                        servicenode->recendtime = 1;
1000        }
1001        if(mbox != NULL && strstr(mbox->name, "change") == mbox->name)
1002        {
1003                servicenode = getrecordbyname(mbox->name, RECORDDIRECT);
1004                if(servicenode != NULL)
1005                {
1006                        ret1 = (servicenode->recendtime - time(NULL)) / 60;
1007                        ret1 = screenrecordduration(ret1);
1008                        if(ret1 > 0)
1009                                servicenode->recendtime = time(NULL) + (ret1 * 60);
1010                }
1011        }
1012        if(ostrcmp(mbox->name, "add recording (stop after current event)") == 0)
1013        {
1014                epgnode = getepgbytime(status.aktservice->channel, time(NULL) + 60);
1015#ifndef SIMULATE
1016                if(epgnode != NULL && epgnode->endtime > time(NULL))
1017                        ret = recordstart(status.aktservice->channel, -1, 0, RECDIRECT, epgnode->endtime, NULL);
1018                else
1019                        textbox(_("Message"), _("Can't get EPG time or EPG endtime not ok"), _("EXIT"), getrcconfigint("rcexit", NULL), NULL, 0, NULL, 0, NULL, 0, 600, 200, 0, 0);
1020#else
1021                ret = recordstart(status.aktservice->channel, -1,  0, RECDIRECT, time(NULL) + 5, NULL);
1022#endif
1023        }
1024        if(ostrcmp(mbox->name, "add recording (indefinitely)") == 0)
1025                ret = recordstart(status.aktservice->channel, -1, 0, RECDIRECT, 0, NULL);
1026        if(ostrcmp(mbox->name, "add recording (enter duration)") == 0)
1027        {
1028                ret1 = screenrecordduration(0);
1029
1030                if(ret1 > 0)
1031                        ret = recordstart(status.aktservice->channel, -1, 0, RECDIRECT, time(NULL) + (ret1 * 60), NULL);
1032        }
1033
1034        recordcheckret(NULL, ret, 6);
1035        freemenulist(mlist, 1); mlist = NULL;
1036}
1037
1038#endif
Note: See TracBrowser for help on using the repository browser.