source: titan/titan/record.h @ 36013

Last change on this file since 36013 was 36013, checked in by Stephan, 8 years ago

[titan] don't add seconds to record file name

File size: 43.4 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"), NULL, 0, 0);
38                                break;
39                        case 2:
40                                tmpstr = ostrcat(_("Not enought space"), NULL, 0, 0);
41                                break;
42                        case 3:
43                                tmpstr = ostrcat(_("Error create filename"), NULL, 0, 0);
44                                break;
45                        case 4:
46                                tmpstr = ostrcat(_("Can't open file"), NULL, 0, 0);
47                                break;
48                        case 5:
49                                tmpstr = ostrcat(_("Can't open FRONTEND device"), NULL, 0, 0);
50                                break;
51                        case 6:
52                                tmpstr = ostrcat(_("Can't open DMX device"), NULL, 0, 0);
53                                break;
54                        case 7:
55                                tmpstr = ostrcat(_("Pid's not ok"), NULL, 0, 0);
56                                break;
57                        case 8:
58                                tmpstr = ostrcat(_("Channel or Transponder is empty"), NULL, 0, 0);
59                                break;
60                        case 9:
61                                tmpstr = ostrcat(_("Write error"), NULL, 0, 0);
62                                break;
63                        case 10:
64                                tmpstr = ostrcat(_("No memory"), NULL, 0, 0);
65                                break;
66                        case 11:
67                                tmpstr = ostrcat(_("Failed open split file"), NULL, 0, 0);
68                                break;
69                        case 12:
70                                tmpstr = ostrcat(_("Frontend type unknown"), NULL, 0, 0);
71                                break;
72                        case 13:
73                                tmpstr = ostrcat(_("Tune to channel failed"), NULL, 0, 0);
74                                break;
75                        case 14:
76                                break;
77                        case 15:
78                                tmpstr = ostrcat(_("To many read error or end of file"), NULL, 0, 0);
79                                break;
80                        case 16:
81                                tmpstr = ostrcat(_("Can't create service"), NULL, 0, 0);
82                                break;
83                        case 17:
84                                tmpstr = ostrcat(_("No space left on device"), NULL, 0, 0);
85                                break;
86                }
87                if(tmpstr != NULL)
88                {
89                        if(checkbit(flag, 2) == 1) err("%s", tmpstr);
90                        if(checkbit(flag, 1) == 1) textbox(_("Record / Timeshift / Stream"), tmpstr, _("EXIT"), getrcconfigint("rcexit", NULL), NULL, 0, NULL, 0, NULL, 0, 800, 200, timeout, 0);
91                }
92        }
93        if(checkbit(flag, 3) == 0)
94        {
95                free(tmpstr);
96                tmpstr = NULL;
97        }
98        return tmpstr;
99}
100
101void recordwriteepg(char* filename, struct channel* chnode, struct rectimer* rectimernode)
102{
103        struct epg* epgnode = NULL;
104        FILE *fd = NULL;
105        int ret = 0, count = 0;
106        char* tmpstr = NULL, *epgfilename = NULL, *buf = NULL;
107        struct tm *loctime = NULL;
108
109        if(filename == NULL)
110        {
111                err("epg record filename = NULL");
112                return;
113        }
114
115        epgfilename = changefilenameext(filename, ".epg");
116       
117        //check if epg is in rectimer time
118        if(rectimernode != NULL)
119        {
120                epgnode = getepgakt(chnode);
121                while(epgnode != NULL && (epgnode->starttime < rectimernode->begin || epgnode->starttime >= rectimernode->end))
122                        epgnode = epgnode->next;
123        }
124        else
125                epgnode = getepgbytime(chnode, time(NULL) + 60);
126       
127        if(epgnode != NULL)
128        {
129                fd = fopen(epgfilename, "w");
130                if(fd == NULL)
131                {
132                        perr("open %s", epgfilename);
133                        free(epgfilename);
134                        return;
135                }
136                chmod(epgfilename, 0666);
137
138                if(epgnode->title != NULL)
139                {
140                        buf = malloc(MINMALLOC);
141                        loctime = localtime(&epgnode->starttime);
142                        strftime(buf, MINMALLOC, "%d-%m-%Y %H:%M", loctime);
143                        ret += fwrite(buf, strlen(buf), 1, fd);
144                        ret += fwrite(" - ", 3, 1, fd);
145                        ret += fwrite(epgnode->title, strlen(epgnode->title), 1, fd);
146                        ret += fwrite("\n", 1, 1, fd);
147                        count += 4;
148                        free(buf); buf = NULL;
149                }
150                if(epgnode->subtitle != NULL)
151                {
152                        ret += fwrite(epgnode->subtitle, strlen(epgnode->subtitle), 1, fd);
153                        ret += fwrite("\n\n", 2, 1, fd);
154                        count += 2;
155                }
156                if(epgnode->desc != NULL)
157                {
158                        tmpstr = epgdescunzip(epgnode);
159                        if(tmpstr != NULL)
160                        {
161                                ret += fwrite(tmpstr, strlen(tmpstr), 1, fd);
162                                count++;
163                                free(tmpstr); tmpstr = NULL;
164                        }
165                }
166
167                if(ret != count)
168                {
169                        err("writting record epg file ret=%d, count=%d", ret, count);
170                }
171
172                fclose(fd);
173        }
174        free(epgfilename);
175}
176
177void createrecthumblastthread(struct stimerthread* self, char* dname, char* filename)
178{
179        if(status.mediadbthread != NULL || self == NULL) return;
180
181        debug(777, "createrecthumbfirst thread (record thumb) start");
182
183        status.mediadbthreadstatus = 1;
184        status.mediadbthread = self;
185        status.mediadbsavetime = 1;
186
187        if(dname != NULL && filename != NULL)
188        {
189                readmediadb(getconfig("mediadbfile", NULL), 0, 0);
190
191                debug(133, "path: %s",dname);
192                debug(133, "file: %s",filename);
193                debug(133, "type: 2");
194       
195                addconfigtmp("mediadbscantimeout", "0");
196                mediadbfindfilecb(dname, filename, 0, NULL, 0);
197                delconfigtmp("mediadbscantimeout");
198        }
199
200        free(dname); dname = NULL;
201        free(filename); filename = NULL;
202        status.mediadbsavetime = 0;
203        status.mediadbthread = NULL;
204        status.mediadbthreadstatus = 0;
205
206        debug(777, "createrecthumbfirst thread (record thumb) end");
207}
208
209void createrecthumbfirstthread(struct stimerthread* self, char* dname, char* filename)
210{
211        debug(777, "createrecthumblast thread (record thumb) start");
212       
213        int count = 0;
214
215        while(count < 600)
216        {
217                sleep(1);
218                count++;
219        }
220
221        if(status.recording > 0)
222        {
223                char* cmd = NULL;
224                cmd = ostrcat("/sbin/grab -v -j 100 -r 1280:720 /tmp/screenshot_backdrop1.jpg", NULL, 0, 0);
225       
226                if(cmd != NULL)
227                        system(cmd);
228                debug(777, "cmd: %s", cmd);
229
230                free(cmd);
231        }
232
233        count = 0;
234        while(count < 60)
235        {
236                sleep(1);
237                count++;
238        }
239
240        if(status.recording > 0)
241        {
242                char* cmd = NULL;
243                cmd = ostrcat("/sbin/grab -v -j 100 -r 500:400 /tmp/screenshot_cover.jpg", NULL, 0, 0);
244       
245                if(cmd != NULL)
246                        system(cmd);
247                debug(777, "cmd: %s", cmd);
248
249                free(cmd);
250        }
251
252        count = 0;
253        while(count < 10)
254        {
255                sleep(1);
256                count++;
257        }
258
259        if(status.recording > 0)
260        {
261                char* cmd = NULL;
262                cmd = ostrcat("/sbin/grab -v -j 100 -r 160:120 /tmp/screenshot_thumb.jpg", NULL, 0, 0);
263       
264                if(cmd != NULL)
265                        system(cmd);
266                debug(777, "cmd: %s", cmd);
267
268                free(cmd);
269        }
270
271        debug(777, "createrecthumblast thread (record thumb) end");
272
273}
274
275void recordstop(struct service* node, int ret)
276{
277        struct stimerthread *recthumblastthread = NULL;
278        struct rectimer* rectimernode = NULL;
279        int afterevent = 1, type = -1;
280
281        if(node != NULL)
282        {
283                type = node->type;
284
285                if(node->fedev != NULL && node->type != RECORDTIMESHIFT)
286                        node->fedev->felock--;
287
288                m_lock(&status.rectimermutex, 1);
289                rectimernode = getrectimerbyservice(node);
290                if(rectimernode != NULL && node->recendtime != 2) //2 = manuall rec stop
291                        afterevent = rectimernode->afterevent;
292                m_unlock(&status.rectimermutex, 1);
293
294                char* dname = NULL, *filename = NULL;
295
296                if(type != RECORDSTREAM && type != RECORDTIMESHIFT && type != RECORDPLAY)
297                {
298                        dname = ostrcat(node->recname, NULL, 0, 0);
299                        dname = dirname(dname);
300                        filename = ostrcat(basename(node->recname), NULL, 0, 0);
301                }
302                       
303#ifdef MIPSEL
304                if(node->encoderdev != NULL)
305                {
306                        if(node->videodev != NULL)
307                        {
308                                videostop(node->videodev, 1);
309                                videoclose(node->videodev, -1);
310                                dmxclose(node->dmxvideodev, -1);
311                        }
312                        if(node->audiodev != NULL)
313                        {
314                                audiostop(node->audiodev);
315                                audioclose(node->audiodev, -1);
316                                dmxclose(node->dmxaudiodev, -1);
317                        }
318                        encoderclose(node->encoderdev, -1);
319                }
320#endif
321                delservice(node, 0);
322
323                if(type == RECORDSTREAM)
324                        status.streaming--;
325                else if(type == RECORDTIMESHIFT)
326                {
327                        if(ret != 0) // on error stop timeshift
328                                timeshiftstop(2);
329                        status.timeshift = 0;
330                }
331                else if(type == RECORDPLAY)
332                        status.playing = 0;
333                else
334                        status.recording--;
335       
336                deltranspondertunablestatus();
337
338                if(dname != NULL && filename != NULL && getconfigint("recordpicture", NULL) == 1)
339                        recthumblastthread = addtimer(&createrecthumblastthread, START, 1000, 1, (void*)ostrcat(dname, NULL, 0, 0), (void*)ostrcat(filename, NULL, 0, 0), NULL);
340
341                if(file_exist(getconfig("skriptafterrec", NULL)))
342                {
343                        char* cmd = NULL;
344                        cmd = ostrcat(getconfig("skriptafterrec", NULL), " \"", 0, 0);
345                        cmd = ostrcat(cmd, dname, 1, 0);
346                        cmd = ostrcat(cmd, "/", 1, 0);
347                        cmd = ostrcat(cmd, filename, 1, 0);
348                        cmd = ostrcat(cmd, "\" &", 1, 0);
349                        debug(250, "start cmd: %s", cmd);
350                        system(cmd);
351                        debug(250, "done cmd: %s", cmd);               
352                        free(cmd), cmd = NULL;
353                }
354
355                free(dname), dname = NULL;
356                free(filename), filename = NULL;
357
358                //afterevent: 0 = auto
359                //afterevent: 1 = nothing
360                //afterevent: 2 = standby
361                //afterevent: 3 = poweroff
362                if(afterevent == 0)
363                {
364                        //not needed
365                        //if(status.startmode == 1) afterevent = 2;
366                        //else
367                        if(getwaswakuptimer() == 1) afterevent = 3;
368                }
369                if(afterevent == 2 && status.standby == 0)
370                {
371                        status.standby = 2;
372                        screenstandby();
373                }
374                if(afterevent == 3)
375                {
376                        if(status.recording < 1)
377                        {
378                                //wait for recthumblastthread end before shutdown
379                                int count = 0;
380                                while(gettimer(recthumblastthread) != NULL && count < 60)
381                                {
382                                        sleep(1);
383                                        count++;
384                                }
385                                int ret = 0;
386                                if(status.standby == 0)
387                                        ret = textbox(_("Message"), _("Box recording finished poweroff in 30sec !"), _("EXIT"), getrcconfigint("rcexit", NULL), _("OK"), getrcconfigint("rcok", NULL), NULL, 0, NULL, 0, 900, 200, 30, 0);
388                                if(ret == 0 || ret == 2)
389                                        oshutdown(1, 3);
390                        }
391                }
392        }
393}
394
395//flag 0: record split
396//flag 1: play split
397int recordsplit(struct service* servicenode, int flag)
398{
399        int ret = 0;
400        char* filename = NULL;
401
402        filename = malloc(256);
403        if(filename == NULL)
404        {
405                err("no mem");
406                ret = 10;
407                servicenode->recendtime = 1;
408        }
409        else
410        {
411                if(flag == 0)
412                {
413                        fdatasync(servicenode->recdstfd);
414                        close(servicenode->recdstfd);
415                }
416                else
417                        close(servicenode->recsrcfd);
418
419                servicenode->rectotal = 0;
420                servicenode->reclastsync = 0;
421
422                if(servicenode->reccount < 2)
423                {
424                        if(strlen(servicenode->recname) > 3)
425                                servicenode->recname[strlen(servicenode->recname) - 3] = '\0';
426                }
427                else
428                {
429                        if(strlen(servicenode->recname) > 7)
430                                servicenode->recname[strlen(servicenode->recname) - 7] = '\0';
431                }
432                snprintf(filename, 255, "%s.%03d.ts", servicenode->recname, servicenode->reccount++);
433                free(servicenode->recname);
434                servicenode->recname = filename;
435
436                if(flag == 0)
437                {
438                        debug(250, "split record file - Recording to %s...", filename);
439                }
440                else
441                {
442                        debug(250, "split play file - Playing %s...", filename);
443                }
444
445                if(flag == 0)
446                        servicenode->recdstfd = open(filename, O_WRONLY | O_CREAT | O_LARGEFILE, 0644);
447                else
448                        servicenode->recsrcfd = open(filename, O_RDONLY | O_LARGEFILE | O_NONBLOCK);
449
450                if(flag == 0)
451                {
452                        if(servicenode->recdstfd < 0)
453                        {
454                                debug(250, "split record file - can't open recording file!");
455                                ret = 11;
456                                servicenode->recendtime = 1;
457                        }
458                        else
459                                posix_fadvise(servicenode->recdstfd, 0, 0, POSIX_FADV_RANDOM);
460                }
461                else
462                {
463                        if(servicenode->recsrcfd < 0)
464                        {
465                                debug(250, "split play file - can't open play file!");
466                                ret = 15;
467                                servicenode->recendtime = 1;
468                        }
469                }
470        }
471        return ret;
472}
473
474int readwritethread(struct stimerthread* stimer, struct service* servicenode, int flag)
475{
476        int readret = 0, writeret = 0, ret = 0, recbsize = 0, tmprecbsize = 0, i = 0, pktcount = 0, frbsize = 0, frmulti = 0, frmultiread = 0;
477        int readtimeout = -1, writetimeout = -1;
478        int recsync = 0, frcount = 0, count = 0;
479        unsigned char* buf = NULL, *tmpbuf = NULL;
480        char* retstr = NULL;
481
482        debug(250, "start read-write thread");
483
484        if(servicenode == NULL)
485        {
486                err("servicenode = NULL");
487                return 1;
488        }
489
490        recsync = getconfigint("recsync", NULL);
491        frbsize = servicenode->tssize * 3072; //aligned to 188 and 4096
492
493        if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
494        {
495                recbsize = servicenode->tssize * 1024; //aligned to 188 and 4096
496                readtimeout = 7000000;
497                writetimeout = 7000000; //5 sec
498        }
499               
500        if(servicenode->type == RECORDPLAY || servicenode->type == RECORDSTREAM)
501        {
502                if(servicenode->recdstfd < 0)
503                {
504                        err("destination fd not ok")
505                        return 1;
506                }
507                if(servicenode->type == RECORDPLAY)
508                {
509                        recbsize = servicenode->tssize * 188;
510                        tmprecbsize = 188 * 188;
511                }
512                readtimeout = 7000000;
513                writetimeout = 7000000;
514                if(servicenode->type == RECORDSTREAM)
515                {
516                        recbsize = servicenode->tssize * 1024; //aligned to 188 and 4096
517                        writetimeout = 60000000 * 30; // 30min if player is in pause
518                }
519        }
520       
521#ifdef SIMULATE
522        int fd = open("simulate/record.ts", O_RDONLY | O_LARGEFILE);
523        if(fd < 0)
524        {
525                perr("open simulate/record.ts");
526                return 1;
527        }
528#endif
529
530        buf = malloc(recbsize);
531        if(buf == NULL)
532        {
533                err("no mem");
534                return 1;
535        }
536       
537        if(servicenode->type == RECORDPLAY && servicenode->tssize == 192)
538        {
539                tmpbuf = malloc(tmprecbsize);
540                if(tmpbuf == NULL)
541                {
542                        err("no mem");
543                        return 1;
544                }
545        }
546       
547        if(servicenode->recdmxstart == 0)
548        {
549                dmxstart(servicenode->dmxvideodev);
550                servicenode->recdmxstart = 1;
551        }
552        while(1)
553        {       
554#ifdef SIMULATE
555                servicenode->recsrcfd = fd;
556                readret = dvbreadfd(servicenode->recsrcfd, buf, 0, recbsize, readtimeout, 0);
557                usleep(1000);
558#else
559                if(servicenode->type == RECORDPLAY)
560                {
561                       
562                        if(status.playspeed != 0)
563                        {
564                                if(status.videosize.w > 720)
565                                {
566                                        frmulti = 16;
567                                        frmultiread = 8;
568                                }
569                                else
570                                {
571                                        frmulti = 8;
572                                        frmultiread = 4;
573                                }
574                                                               
575                                if(status.playspeed == -4)
576                                        frmulti = frmulti + (frmulti/2);
577                                else if(status.playspeed == -5)
578                                        frmulti = frmultiread * 4;
579                                else if(status.playspeed == -6)
580                                        frmulti = frmultiread * 8;
581                                else if(status.playspeed == 4)
582                                        frmulti = frmulti + frmultiread ;
583                                else if(status.playspeed == 5)
584                                        frmulti = frmultiread * 4;
585                                else if(status.playspeed == 6)
586                                        frmulti = frmultiread * 8;                             
587                        }                       
588                       
589                        if(frcount == 0 && (status.playspeed < 0 || status.playspeed > 3))
590                        {                               
591                                pthread_mutex_lock(&status.tsseekmutex);
592                                off64_t pos = 0;
593                                if(status.playspeed < 0)
594                                        pos = lseek64(servicenode->recsrcfd, -(frbsize * frmulti), SEEK_CUR);
595                                else if(status.playspeed == 4 || status.playspeed == 5 || status.playspeed == 6)
596                                        pos = lseek64(servicenode->recsrcfd, ((frbsize * frmulti) - ( frbsize * frmultiread )), SEEK_CUR);
597
598                                //begin of file
599                                if(pos <= 0)
600                                {
601                                        //videoclearbuffer(status.aktservice->videodev);
602                                        //audioclearbuffer(status.aktservice->audiodev);
603                                        playerpausets();
604                                        playercontinuets();
605                                        playerresetts();
606
607                                        status.playspeed = 0;
608                                        status.pause = 0;
609                                        status.play = 1;
610                                }
611                                else
612                                {
613                                        if(status.playspeed < 0)
614                                                videodiscontinuityskip(status.aktservice->videodev, -1);
615                                        else
616                                                videodiscontinuityskip(status.aktservice->videodev, 1);
617                                }
618                                pthread_mutex_unlock(&status.tsseekmutex);
619                        }
620
621                        if(frcount != 0 && status.playspeed == 0)
622                                frcount = 0;
623                       
624                        pthread_mutex_lock(&status.tsseekmutex);
625                        readret = dvbreadfd(servicenode->recsrcfd, buf, 0, recbsize, readtimeout, 1);
626                        if(readret <= 0 && status.timeshift > 0)
627                        {
628                                playerpausets();
629                                playercontinuets();
630                                //playerresetts();
631                                status.playspeed = 0;
632                                status.pause = 0;
633                                status.play = 1;
634                                playerseekts(servicenode, -3, 1);
635                                readret = dvbreadfd(servicenode->recsrcfd, buf, 0, recbsize, readtimeout, 1);
636                        }
637                        pthread_mutex_unlock(&status.tsseekmutex);                             
638               
639                        if(status.playspeed < 0 || status.playspeed > 0)
640                        {
641                                frcount += readret;
642                                if(frcount >= frbsize * frmultiread)
643                                        frcount = 0;
644                        }
645                }
646                else
647                        readret = dvbreadfd(servicenode->recsrcfd, buf, 0, recbsize, readtimeout, 0);
648#endif
649                if(readret > 0)
650                {
651                        if(servicenode->type == RECORDSTREAM)
652                        {
653//Workaround scrambled Bits
654                                if(getconfigint("stream_workaround_off", NULL) == 0)
655                                        {
656#ifdef MIPSEL
657                                                debug(251, "data len %i", readret);
658                                                if(servicenode->tssize == 188)
659                                                {
660                                                        i = 0;
661                                                        if(buf[i] != 0x47)
662                                                        {
663                                                                debug(251, "no sync byte at beginn len %i", readret);
664                                                                i = 1;
665                                                                while(i <= 188)
666                                                                {
667                                                                        if(buf[i] == 0x47)
668                                                                        {
669                                                                                 debug(251, "sync byte found at offset %i", i);
670                                                                                 break;
671                                                                        }
672                                                                        i++;
673                                                                }
674                                                        }
675                                                        if(i <= 188)
676                                                        {
677                                                                while(i < readret-4)
678                                                                {
679                                                                        if(buf[i] == 0x47)
680                                                                        {
681                                                                                buf[i+3] = buf[i+3] & 0x3f;
682                                                                                i = i + 188;
683                                                                        }
684                                                                        else
685                                                                        {
686                                                                                debug(251, "no sync byte at data len %i", readret);
687                                                                                while(i < readret-4)
688                                                                                {
689                                                                                        i = i + 1;
690                                                                                        if(buf[i] == 0x47)
691                                                                                        {
692                                                                                                debug(251, "sync byte found at offset %i", i);
693                                                                                                buf[i+3] = buf[i+3] & 0x3f;
694                                                                                                i = i + 188;
695                                                                                                break;
696                                                                                        }
697                                                                                }       
698                                                                        }
699                                                                }
700                                                        }
701                                                }
702#endif
703                                        }
704//*
705                                writeret = sockwrite(servicenode->recdstfd, buf, readret, writetimeout);
706                        }
707                        else
708                        {
709                                if(servicenode->type == RECORDPLAY && servicenode->tssize == 192)
710                                {
711                                        // remove 4 bytes per paket from mts and m2ts streams
712                                        pktcount = readret / 192;
713                                        for(i = 0; i < pktcount; i++)
714                                                memcpy(tmpbuf + (i * 188), buf + (i * 192) + 4, 188);
715                                        writeret = dvbwrite(servicenode->recdstfd, tmpbuf, pktcount * 188, writetimeout);
716                                        writeret = writeret + (pktcount * 4);
717                                }
718                                else
719                                {
720                                /*if(buf[0] != 0x47)
721                                {
722                                        debug(200, "resync");
723                                        i = 1;
724                                        while(i < 188)
725                                        {
726                                                if(buf[i] == 0x47) break;
727                                                i++;
728                                        }
729                                        if(i < 188)
730                                        {
731                                                memcpy(buf, buf + i, recbsize - i);
732                                                dvbreadfd(servicenode->recsrcfd, buf, recbsize - i, i, readtimeout, 0);
733                                        }
734                                }*/
735//Workaround scrambled Bits
736                                        if(getconfigint("rec_workaround_off", NULL) == 0)
737                                        {
738#ifndef MIPSEL
739                                                if(servicenode->type == RECORDPLAY)
740                                                {
741#endif                 
742                                                        i = 0;
743                                                        if(buf[i] != 0x47)
744                                                        {
745                                                                i = 1;
746                                                                while(i <= 188)
747                                                                {
748                                                                        if(buf[i] == 0x47) break;
749                                                                        i++;
750                                                                }
751                                                        }
752                                                        if(i <= 188)
753                                                        {
754                                                                while(i < readret-4)
755                                                                {
756                                                                        if(buf[i] == 0x47)
757                                                                        {
758                                                                                buf[i+3] = buf[i+3] & 0x3f;
759                                                                                i = i + 188;
760                                                                        }
761                                                                        else
762                                                                        {
763                                                                                while(i < readret-4)
764                                                                                {
765                                                                                        i = i + 1;
766                                                                                        if(buf[i] == 0x47)
767                                                                                        {
768                                                                                                buf[i+3] = buf[i+3] & 0x3f;
769                                                                                                i = i + 188;
770                                                                                                break;
771                                                                                        }
772                                                                                }       
773                                                                        }
774                                                                }
775                                                        }
776#ifndef MIPSEL
777                                                }                                               
778#endif
779                                        }
780//*
781                                        writeret = dvbwrite(servicenode->recdstfd, buf, readret, writetimeout);
782                                }
783
784                                //inject first pakets slower/smaler, so demux can start and read
785                                if(servicenode->type == RECORDPLAY && count < 20)
786                                {
787                                        if(status.timeshift == 0)
788                                                usleep(50000);
789                                        else
790                                                count = 19;
791                                        if(count == 19)
792                                        {
793                                                recbsize = servicenode->tssize * 1024; //aligned to 188 and 4096
794                                                tmprecbsize = 188 * 1024; //aligned to 188 and 4096
795
796                                                free(buf);
797                                                buf = malloc(recbsize);
798                                                if(buf == NULL)
799                                                {
800                                                        err("no mem");
801                                                        servicenode->recendtime = 1;
802                                                }
803
804                                                if(servicenode->tssize == 192)
805                                                {
806                                                        free(tmpbuf);
807                                                        tmpbuf = malloc(tmprecbsize);
808                                                        if(tmpbuf == NULL)
809                                                        {
810                                                                err("no mem");
811                                                                servicenode->recendtime = 1;
812                                                        }
813                                                }
814                                        }
815                                        count++;
816                                }
817                        }
818
819                        if(writeret < 1)
820                        {
821                                ret = 9;
822                                if(writeret == -ENOSPC) ret = 17;
823                                servicenode->recendtime = 1;
824                        }
825                        else if(readret != writeret)
826                        {
827                                debug(250, "not all data written read=%d, written=%d", readret, writeret);
828                        }
829
830                        if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
831                        {
832                                //sync
833                                if(recsync == 1)
834                                {
835                                        servicenode->reclastsync += writeret;
836                                        if(servicenode->reclastsync > 524288)
837                                        {
838                                                fdatasync(servicenode->recdstfd);
839                                                posix_fadvise64(servicenode->recdstfd, 0, 0, POSIX_FADV_DONTNEED);
840                                                servicenode->reclastsync = 0;
841                                        }
842                                }
843
844                                if(status.recsplitsize && servicenode->type != RECORDTIMESHIFT)
845                                {
846                                        servicenode->rectotal += writeret;
847                                        if(servicenode->rectotal > status.recsplitsize)
848                                                ret = recordsplit(servicenode, 0);
849                                }
850                        }
851                }
852                else if(readret <= 0)
853                {
854                        if(readret == 0 && servicenode->type == RECORDPLAY)
855                        {
856                                if(getconfigint("playsplitfiles", NULL) == 1)
857                                        ret = recordsplit(servicenode, 1);
858                                else
859                                {
860                                        ret = 15;
861                                        servicenode->recendtime = 1;
862                                }
863                        }
864                        else
865                        {
866                                ret = 15;
867                                servicenode->recendtime = 1;
868                        }
869
870                        if(readret < -1)
871                                perr("read");
872                }
873
874                if(servicenode->recendtime != 0 && servicenode->recendtime < time(NULL))
875                {
876                        if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
877                                fdatasync(servicenode->recdstfd);
878                        if(ret != 0) // error
879                        {
880                                if(servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)
881                                        addtimer(&recordcheckret, START, 1000, 1, (void*)ret, (void*)3, NULL);
882                                retstr = recordcheckret(NULL, ret, 12);
883
884                                //if(servicenode->type == RECORDSTREAM)
885                                //      sockwrite(servicenode->recdstfd, (unsigned char*)retstr, strlen(retstr), -1);
886                                if(servicenode->type == RECORDTIMER)
887                                {
888                                        m_lock(&status.rectimermutex, 1);
889                                        struct rectimer* rectimernode = getrectimerbyservice(servicenode);
890                                        if(rectimernode != NULL)
891                                        {
892                                                rectimernode->status = 3;
893                                                free(rectimernode->errstr);
894                                                rectimernode->errstr = ostrcat(retstr, NULL, 0, 0);
895                                                status.writerectimer = 1;
896                                                writerectimer(getconfig("rectimerfile", NULL), 1);
897                                        }
898                                        m_unlock(&status.rectimermutex, 1);
899                                }
900                                free(retstr); retstr = NULL;
901                        }
902                        recordstop(servicenode, ret);
903                        break;
904                }
905        }
906
907#ifdef SIMULATE
908        close(fd);
909#endif
910        if(buf != NULL) free(buf);
911        if(tmpbuf != NULL) free(tmpbuf);
912        debug(250, "stop read-write thread");
913        return 0;
914}
915
916char* recordcreatefilename(char* path, char* channelname, char* moviename, int type)
917{
918        time_t sec;
919        struct tm *loctime;
920        char *buf = NULL, *buf1 = NULL;
921        char* tmpstr = NULL;
922        int recordnamefmt = getconfigint("recordnamefmt", NULL);
923
924        if(path == NULL)
925                return NULL;
926
927        tmpstr = ostrcat(path, "/", 0, 0);
928        if(type != RECTIMESHIFT && recordnamefmt == 0)
929        {
930                tmpstr = ostrcat(tmpstr, "(", 1, 0);
931                if(channelname == NULL || strlen(channelname) == 0)
932                        tmpstr = ostrcat(tmpstr, "unknown", 1, 0);
933                else
934                        tmpstr = ostrcat(tmpstr, channelname, 1, 0);
935                tmpstr = ostrcat(tmpstr, ") ", 1, 0);
936        }
937
938        if(moviename == NULL || strlen(moviename) == 0)
939                tmpstr = ostrcat(tmpstr, "unknown", 1, 0);
940        else
941                tmpstr = ostrcat(tmpstr, moviename, 1, 0);
942
943        if(type != RECTIMESHIFT && recordnamefmt == 1)
944        {
945                tmpstr = ostrcat(tmpstr, " (", 1, 0);
946                if(channelname == NULL || strlen(channelname) == 0)
947                        tmpstr = ostrcat(tmpstr, "unknown", 1, 0);
948                else
949                        tmpstr = ostrcat(tmpstr, channelname, 1, 0);
950        }
951
952        sec = time(NULL);
953        loctime = localtime(&sec);
954
955        buf = malloc(MINMALLOC);
956        if(buf == NULL)
957        {
958                err("no memory");
959                return NULL;
960        }
961
962        strftime(buf, MINMALLOC, "%Y%m%d%H%M", loctime);
963        buf1 = ostrcat(buf, NULL, 1, 0);
964
965        if(type != RECTIMESHIFT && recordnamefmt == 1)
966                tmpstr = ostrcat(tmpstr, "-", 1, 0);
967        else
968                tmpstr = ostrcat(tmpstr, " (", 1, 0);   
969        tmpstr = ostrcat(tmpstr, buf1, 1, 1);
970        tmpstr = ostrcat(tmpstr, ")", 1, 0);
971        if(ostrcmp(channelname, "HDMIIN") == 0)
972                tmpstr = ostrcat(tmpstr, ".mpeg", 1, 0);
973        else
974                tmpstr = ostrcat(tmpstr, ".ts", 1, 0);
975
976        return tmpstr;
977}
978
979int recordstartreal(struct channel* chnode, int filefd, int recordfd, int type, time_t endtime, struct rectimer* rectimernode, int tssize)
980{
981        int ret = 0, fd = -1, servicetype = RECORDDIRECT, festatus = 0, pcrpidmatch = 0;
982        char* path = NULL, *chname = NULL, *filename = NULL, *moviename = NULL;
983        unsigned char* patbuf = NULL, *pmtbuf = NULL;
984        struct epg* epgnode = NULL;
985        struct service* servicenode = NULL;
986        struct dvbdev* fenode = NULL, *dmxnode = NULL;
987#ifdef MIPSEL
988        struct dvbdev* encnode = NULL, *videonode = NULL, *audionode = NULL;
989#endif
990        struct audiotrack* atrack = NULL;
991        struct subtitle *subnode = NULL;
992        char* tmpstr = NULL;
993        struct transponder* tpnode = NULL;
994        int input = DMX_IN_FRONTEND;
995
996        //wakeup hdd work
997        if(type != RECSTREAM && type != RECSTREAMENC)
998                wakeup_record_device();
999
1000        if(chnode == NULL && filefd < 0)
1001        {
1002                ret = 8;
1003                goto end;
1004        }
1005
1006        //hdmi record.. serviceid=65535
1007        if(filefd < 0 && chnode->serviceid != 65535)
1008        {
1009                tpnode = chnode->transponder;
1010                if(tpnode == NULL)
1011                {
1012                        ret = 8;
1013                        goto end;
1014                }
1015        }
1016
1017        switch(type)
1018        {
1019                case RECPLAY:
1020                        servicetype = RECORDPLAY;
1021                        fd = recordfd;
1022                        break;
1023                case RECSTREAM:
1024                        servicetype = RECORDSTREAM;
1025                        fd = recordfd;
1026                        break;
1027                case RECSTREAMENC:
1028                        servicetype = RECORDSTREAM;
1029                        fd = recordfd;
1030                        break;
1031                case RECTIMESHIFT:
1032                        servicetype = RECORDTIMESHIFT;
1033                        path = getconfig("rec_timeshiftpath", NULL);
1034                        moviename = "timeshift";
1035                        break;
1036                case RECTIMER:
1037                        servicetype = RECORDTIMER;
1038                        if(rectimernode != NULL && rectimernode->recpath != NULL)
1039                                path = rectimernode->recpath;
1040                        else
1041                                path = getconfig("rec_timerpath", NULL);
1042                        if(chnode != NULL)
1043                        {
1044                                chname = strstrip(chnode->name);
1045                                delspezchar(chname, 2);
1046                        }
1047                        if(rectimernode != NULL && rectimernode->name != NULL)
1048                        {
1049                                moviename = strstrip(rectimernode->name);
1050                                delspezchar(moviename, 2);
1051                        }
1052                        break;
1053                default:
1054                        servicetype = RECORDDIRECT;
1055                        path = getconfig("rec_path", NULL);
1056                        if(chnode != NULL)
1057                        {
1058                                chname = strstrip(chnode->name);
1059                                delspezchar(chname, 2);
1060                        }
1061                        epgnode = getepgbytime(status.aktservice->channel, time(NULL) + 60);
1062                        if(epgnode != NULL)
1063                        {
1064                                moviename = strstrip(epgnode->title);
1065                                delspezchar(moviename, 2);
1066
1067                        }
1068                        break;
1069        }
1070
1071        if(type != RECSTREAM && type != RECSTREAMENC && type != RECPLAY)
1072        {
1073                if(!isdir(path))
1074                {
1075                        ret = 1;
1076                        goto end;
1077/*
1078not needed we use wakeup_record_device on recordstartreal
1079                        char *dev = NULL;
1080                        dev = getmoviedev();
1081                        if(dev == NULL)
1082                        {
1083                                ret = 1;
1084                                goto end;
1085                        }
1086                        else
1087                        {
1088                                free(dev);dev=NULL;
1089                                sleep(3);
1090                                if(!isdir(path))
1091                                {
1092                                        ret = 1;
1093                                        goto end;
1094                                }
1095                        }
1096*/
1097                }
1098
1099                //check HDD free space
1100                //deaktivate, on my 500GB FAT32 HDD, this takes mor then 10 min
1101#ifdef MIPSEL
1102                if(getfreespace(path) < getconfigint("recordfreespace", NULL) * 1024 * 1024)
1103                {
1104                        ret = 2;
1105                        goto end;
1106                }
1107#endif
1108
1109                filename = recordcreatefilename(path, chname, moviename, type);
1110                if(filename == NULL)
1111                {
1112                        ret = 3;
1113                        goto end;
1114                }
1115
1116                fd = open(filename, O_WRONLY | O_CREAT | O_LARGEFILE, 0666);
1117                if(fd < 0)
1118                {
1119                        char* fn = strrchr(filename, '/');
1120                        if(fn == NULL)
1121                                delspezchar(filename, 0);
1122                        else
1123                                delspezchar(fn + 1, 0);
1124       
1125                        fd = open(filename, O_WRONLY | O_CREAT | O_LARGEFILE, 0666);
1126                        if(fd < 0)
1127                        {
1128                                ret = 4;
1129                                goto end;
1130                        }
1131                }
1132                posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM); //turn off kernel cache
1133        }
1134
1135        servicenode = addservice(NULL);
1136        if(servicenode == NULL)
1137        {
1138                ret = 16;
1139                goto end;
1140        }
1141        servicenode->tssize = tssize;
1142        servicenode->recdstfd = fd;
1143        servicenode->channel = chnode;
1144        servicenode->transponder = tpnode;
1145        if(rectimernode != NULL) servicenode->rectimestamp = ostrcat(rectimernode->timestamp, NULL, 0, 0);
1146
1147        if(filefd < 0 && chnode->serviceid != 65535)
1148        {
1149                //got frontend dev
1150                fenode = fegetfree(tpnode, 2, NULL);
1151                if(fenode == NULL)
1152                {
1153                        if(status.standby == 0 && (type == RECSTREAM || type == RECSTREAMENC))
1154                        {
1155                                ret = 5;
1156                                goto end;
1157                        }
1158                        else
1159                        {
1160                                if(status.standby == 0 && 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, 800, 200, 10, 0) == 1)
1161                                {
1162                                        ret = 14;
1163                                        goto end;
1164                                }
1165                                else
1166                                {
1167                                        if(rectimernode != NULL)
1168                                                servicestart(chnode, rectimernode->channellist, rectimernode->pincode, 0);
1169                                        else
1170                                                servicestart(chnode, NULL, NULL, 0);
1171                                       
1172                                        if(status.standby > 0) servicestop(status.aktservice, 1, 0);   
1173                                       
1174                                        fenode = fegetfree(tpnode, 2, NULL);
1175                                        if(fenode == NULL)
1176                                        {
1177                                                ret = 5;
1178                                                goto end;
1179                                        }
1180                                }
1181                        }
1182                }
1183                if(type != RECTIMESHIFT) fenode->felock++;
1184
1185                //frontend tune
1186                if(fenode != status.aktservice->fedev || (status.standby > 0 && getconfigint("standbytuneroff", NULL) == 1))
1187                {
1188                        if(fenode->feinfo->type == FE_QPSK)
1189                        {
1190                                feset(fenode, tpnode);
1191                                fetunedvbs(fenode, tpnode);
1192                        }
1193                        else if(fenode->feinfo->type == FE_QAM)
1194                                fetunedvbc(fenode, tpnode);
1195                        else if(fenode->feinfo->type == FE_OFDM)
1196                                fetunedvbt(fenode, tpnode);
1197                        else
1198                        {
1199                                ret = 12;
1200                                if(type != RECTIMESHIFT) fenode->felock--;
1201                                goto end;
1202                        }
1203
1204                        festatus = fewait(fenode);
1205                        if(debug_level == 200) fereadstatus(fenode);
1206                        if(festatus != 0)
1207                        {
1208                                ret = 13;
1209                                if(type != RECTIMESHIFT) fenode->felock--;
1210                                goto end;
1211                        }
1212                }
1213
1214                servicenode->fedev = fenode;
1215
1216                //demux  start
1217                dmxnode = dmxopen(fenode, 1);
1218                if(dmxnode != NULL && dmxnode->fd >= 0)
1219                {
1220                        servicenode->recsrcfd = dmxnode->fd;
1221                        if(type == RECTIMESHIFT)
1222                                dmxsetbuffersize(dmxnode, getconfigint("dmxtimeshiftbuffersize", NULL));
1223                        else if(type == RECSTREAM || type == RECSTREAMENC )
1224                                dmxsetbuffersize(dmxnode, getconfigint("dmxstreambuffersize", NULL));
1225                        else
1226                                dmxsetbuffersize(dmxnode, getconfigint("dmxrecordbuffersize", NULL));
1227                        servicenode->dmxaudiodev = dmxnode;
1228                        servicenode->dmxvideodev = dmxnode;
1229                        dmxsetsource(dmxnode, fenode->fedmxsource);
1230#if DVB_API_VERSION > 3
1231                        dmxsetpesfilter(dmxnode, 0, input, DMX_OUT_TSDEMUX_TAP, DMX_PES_OTHER, 1);
1232#else
1233                        dmxsetpesfilter(dmxnode, 0, input, DMX_OUT_TAP, 0, 1);
1234#endif
1235                        patbuf = dvbgetpat(fenode, -1);
1236                        chnode->pmtpid = dvbgetpmtpid(patbuf, chnode->serviceid);
1237
1238                        m_lock(&status.servicemutex, 2);
1239                        if(status.aktservice->channel != chnode)
1240                        {
1241                                //reset channel info
1242                                serviceresetchannelinfo(chnode);
1243                                pmtbuf = dvbgetpmt(fenode, patbuf, chnode->serviceid, &chnode->pmtpid, NULL, -1, 0);
1244                                dvbgetinfo(pmtbuf, chnode);
1245                        }
1246                        if(status.pmtmode == 1)
1247                        {
1248                                if(recordcheckcrypt(fenode, servicetype) == 0)
1249                                        dvbwritepmt(servicenode, pmtbuf);
1250                                else
1251                                        debug(250, "don't write pmt.tmp, another crypt channel use this frontend");
1252                        }
1253                        else
1254                                sendcapmt(servicenode, 0, 3);
1255                        m_unlock(&status.servicemutex, 2);
1256
1257                        free(pmtbuf); pmtbuf = NULL;
1258                        free(patbuf); patbuf = NULL;
1259                        if((chnode->audiopid < 1 && chnode->videopid < 1) || chnode->pmtpid < 1)
1260                        {
1261#ifndef SIMULATE
1262                                ret = 7;
1263                                if(type != RECTIMESHIFT) fenode->felock--;
1264                                goto end;
1265#endif
1266                        }
1267#ifdef MIPSEL
1268                        if(type == RECSTREAMENC)
1269                        {
1270       
1271                                dmxclose(dmxnode, -1);
1272
1273                                encnode = encoderopen(0);
1274                                servicenode->encoderdev = encnode;
1275                               
1276                                servicenode->dmxaudiodev = dmxopen(fenode, 2);
1277                                dmxsetbuffersize(servicenode->dmxaudiodev, getconfigint("dmxaudiobuffersize", NULL));
1278                                dmxsetsource(servicenode->dmxaudiodev, fenode->fedmxsource);
1279                                switch(encnode->decoder)
1280                                {
1281                                        case 2: dmxsetpesfilter(servicenode->dmxaudiodev, chnode->audiopid, -1, DMX_OUT_DECODER, DMX_PES_AUDIO2, 0); break;
1282                                        case 3: dmxsetpesfilter(servicenode->dmxaudiodev, chnode->audiopid, -1, DMX_OUT_DECODER, DMX_PES_AUDIO3, 0); break;
1283                                }
1284
1285                                audionode = audioopen(encnode->decoder);
1286                                servicenode->audiodev = audionode;
1287                                audioselectsource(servicenode->audiodev, AUDIO_SOURCE_DEMUX);
1288                                if(chnode->audiocodec != AC3)
1289                                        audiosetbypassmode(servicenode->audiodev, 1);
1290                                else
1291                                        audiosetbypassmode(servicenode->audiodev, 0);
1292                                audioplay(servicenode->audiodev);
1293                               
1294                                servicenode->dmxvideodev = dmxopen(fenode, 2);
1295                                dmxsetbuffersize(servicenode->dmxvideodev, getconfigint("dmxvideobuffersize", NULL));
1296                                dmxsetsource(servicenode->dmxvideodev, fenode->fedmxsource);
1297                               
1298                                switch(encnode->decoder)
1299                                {
1300                                        case 2: dmxsetpesfilter(servicenode->dmxvideodev, chnode->videopid, -1, DMX_OUT_DECODER, DMX_PES_VIDEO2, 0); break;
1301                                        case 3: dmxsetpesfilter(servicenode->dmxvideodev, chnode->videopid, -1, DMX_OUT_DECODER, DMX_PES_VIDEO3, 0); break;
1302                                }
1303                               
1304                                videonode = videoopen(0, encnode->decoder);
1305                                servicenode->videodev = videonode;
1306                                videoselectsource(servicenode->videodev, VIDEO_SOURCE_DEMUX);
1307                                setencoding(chnode, servicenode->videodev);
1308                                videoplay(servicenode->videodev);
1309                                 
1310                                encnode->fd = encoderopendirect(encnode->dev);
1311                                servicenode->recdmxstart = 1;
1312                                servicenode->recsrcfd = encnode->fd;
1313                        }
1314                        else
1315                        {
1316#endif
1317                                if(chnode->audiopid > 0) dmxaddpid(dmxnode, chnode->audiopid);
1318                                if(chnode->videopid > 0) dmxaddpid(dmxnode, chnode->videopid);
1319                                dmxaddpid(dmxnode, chnode->pmtpid);
1320                                //add all audiotracks
1321                                atrack = chnode->audiotrack;
1322                                while(atrack != NULL)
1323                                {
1324                                        if(atrack->audiopid > 0 && atrack->audiopid != chnode->audiopid)
1325                                                dmxaddpid(dmxnode, atrack->audiopid);
1326                                        if(atrack->audiopid == chnode->pcrpid) pcrpidmatch = 1;
1327                                        atrack = atrack->next;
1328                                }
1329                                if(chnode->pcrpid > 0 && chnode->pcrpid != chnode->videopid && chnode->pcrpid != chnode->audiopid && pcrpidmatch == 0) dmxaddpid(dmxnode, chnode->pcrpid);
1330                       
1331                                //add all subtitle
1332                                m_lock(&status.subtitlemutex, 8);
1333                                subnode = chnode->subtitle;
1334                                while(subnode != NULL)
1335                                {
1336                                        if(subnode->pid > 0)
1337                                                dmxaddpid(dmxnode, subnode->pid);
1338                                        subnode = subnode->next;
1339                                }
1340                                m_unlock(&status.subtitlemutex, 8);
1341                       
1342                                //add epg pid
1343                                if(getconfigint("epg2record", NULL) == 1) dmxaddpid(dmxnode, 0x12);     
1344#ifdef MIPSEL
1345                        }
1346#endif
1347                }
1348                else
1349                {
1350                        ret = 6;
1351                        if(type != RECTIMESHIFT) fenode->felock--;
1352                        goto end;
1353                }
1354        }
1355#ifdef MIPSEL
1356        if(filefd < 0 && chnode->serviceid == 65535)
1357        //else if(chnode->serviceid == 65535 && servicetype == RECORDDIRECT)
1358        {
1359                ret = encoderset(-1, 1, 1024*1024*8, 1280, 720, 25000, 0, 0);
1360                ret = 0;
1361                encnode = encoderopen(0);
1362                servicenode->encoderdev = encnode;
1363               
1364                videonode = videoopen(0, encnode->decoder);
1365                servicenode->videodev = videonode;
1366                videoselectsource(servicenode->videodev, VIDEO_SOURCE_HDMI);
1367                videoplay(servicenode->videodev);
1368
1369                audionode = audioopen(encnode->decoder);
1370                servicenode->audiodev = audionode;
1371                audioselectsource(servicenode->audiodev, AUDIO_SOURCE_HDMI);
1372                audioplay(servicenode->audiodev);
1373
1374                encnode->fd = encoderopendirect(encnode->dev);
1375                servicenode->recdmxstart = 1;
1376                servicenode->recsrcfd = encnode->fd;
1377        }
1378#endif
1379        if(rectimernode != NULL)
1380                rectimernode->servicenode = servicenode;
1381
1382        servicenode->recendtime = endtime;
1383        servicenode->reccount = 1;
1384        servicenode->type = servicetype;
1385
1386        if(filefd < 0)
1387                deltranspondertunablestatus();
1388        else
1389                servicenode->recsrcfd = filefd;
1390#ifdef MIPSEL
1391        if(type == RECSTREAMENC)
1392                servicenode->recsrcfd = encnode->fd;
1393#endif
1394
1395        if(type == RECSTREAM || type == RECSTREAMENC)
1396        {
1397                status.streaming++;
1398                servicenode->recname = ostrcat("stream ", oitoa(recordfd), 0, 1);
1399        }
1400        else if(type == RECTIMESHIFT)
1401        {
1402                status.timeshift = 1;
1403                servicenode->recname = ostrcat(filename, NULL, 0, 0);
1404        }
1405        else if(type == RECPLAY)
1406        {
1407                status.playing = 1;
1408                servicenode->recdmxstart = 1;
1409        }
1410        else if(type == RECDIRECT || type == RECTIMER)
1411        {
1412                status.recording++;
1413                servicenode->recname = ostrcat(filename, NULL, 0, 0);
1414                if(VFD_Recordthread == NULL && getconfigint("vfdisplayrecord", NULL) != 0)
1415                        VFD_Recordthread = addtimer(&vfdrecordthread, START, 10000, 1, NULL, NULL, NULL);
1416#ifdef MIPSEL
1417                if(chnode->serviceid == 65535)
1418                        servicenode->recsrcfd = encnode->fd;
1419#endif
1420        }
1421
1422        if(type != RECSTREAM && type != RECSTREAMENC && type != RECTIMESHIFT && type != RECPLAY)
1423                recordwriteepg(filename, chnode, rectimernode);
1424
1425        //start readwrite thread
1426        addtimer(&readwritethread, START, 1000, 1, (void*)servicenode, NULL, NULL);
1427
1428        if(type == RECTIMER && status.standby == 0)
1429        {
1430                char* subfile = NULL;
1431                subfile = ostrstr(filename, "/movie/");
1432                if(subfile != NULL)
1433                        subfile = subfile + 7;
1434                else
1435                        subfile = filename;
1436                tmpstr = ostrcat(_("Timer Record start !"), subfile, 0, 0);
1437                textbox(_("Message"), tmpstr, _("OK"), getrcconfigint("rcok", NULL), NULL, 0, NULL, 0, NULL, 0, 900, 200, 4, 0);
1438                free(tmpstr); tmpstr = NULL;
1439        }
1440       
1441        if(filename != NULL) debug(250, "rec filename = %s\n", filename);
1442
1443end:
1444        if(ret > 0)
1445        {
1446                delservice(servicenode, 1);
1447                if(filename != NULL) unlink(filename);
1448        }
1449        free(filename); filename = NULL;
1450        return ret;
1451}
1452
1453#ifdef MIPSEL
1454int recordstartencode(struct channel* chnode, int filefd, int recordfd, int type, time_t endtime, struct rectimer* rectimernode,        int bitrate, int width, int height, int framerate, int interlaced, int aspectratio)
1455{
1456        if(type == RECSTREAMENC)
1457        {
1458                if(bitrate == 0)
1459                {
1460                        if(encodersetweb(-1, 1) != 0)
1461                                return -1;
1462                }       
1463                else if(encoderset(-1, 1, bitrate, width, height, framerate, interlaced, aspectratio) != 0)
1464                        return -1;
1465        }       
1466        return recordstartreal(chnode, filefd, recordfd, type, endtime, rectimernode, 188);
1467}
1468#endif
1469               
1470int recordstart(struct channel* chnode, int filefd, int recordfd, int type, time_t endtime, struct rectimer* rectimernode)
1471{
1472        return recordstartreal(chnode, filefd, recordfd, type, endtime, rectimernode, 188);
1473}
1474
1475struct service* getrecordbyname(char* recname, int type)
1476{
1477        struct service* servicenode = service;
1478
1479        if(recname == NULL)
1480        {
1481                err("NULL detect");
1482                return NULL;
1483        }
1484
1485        while(servicenode != NULL)
1486        {
1487                if((type == -1 && (servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER || servicenode->type == RECORDTIMESHIFT)) || type == servicenode->type)
1488                {
1489                        if(servicenode->recname != NULL)
1490                        {
1491                                if(ostrstr(recname, servicenode->recname) != NULL)
1492                                        return servicenode;
1493                        }
1494                }
1495                servicenode = servicenode->next;
1496        }
1497
1498        return NULL;
1499}
1500
1501int screenrecordduration(int minutes, int nextmin)
1502{
1503                int rcret = 0, ret = 0;
1504                struct skin* recordduration = getscreen("recordduration");
1505                struct skin* b1 = getscreennode(recordduration, "b1");
1506                char* tmpnr = NULL;
1507
1508                if(nextmin == 0)
1509                        b1->hidden = YES;
1510                else
1511                {
1512                        if(nextmin > 9999) nextmin = 9999;
1513                        b1->hidden = NO;
1514                }
1515
1516                changemask(recordduration, "0000");
1517                if(minutes < 0) minutes = 0;
1518                if(minutes > 9999) minutes = 9999;
1519                tmpnr = malloc(5);
1520                snprintf(tmpnr, 5, "%04d", minutes);
1521                changeinput(recordduration, tmpnr);
1522                free(tmpnr); tmpnr = NULL;
1523
1524                drawscreen(recordduration, 0, 0);
1525                addscreenrc(recordduration, recordduration);
1526
1527                while(1)
1528                {
1529                        rcret = waitrc(recordduration, 0, 0);
1530                        if(nextmin > 0 && rcret == getrcconfigint("rcred", NULL))
1531                        {
1532                                changemask(recordduration, "0000");
1533                                tmpnr = malloc(5);
1534                                snprintf(tmpnr, 5, "%04d", nextmin);
1535                                changeinput(recordduration, tmpnr);
1536                                changeret(recordduration, tmpnr);
1537                                free(tmpnr); tmpnr = NULL;
1538                                drawscreen(recordduration, 0, 0);
1539                        }
1540                        if(rcret == getrcconfigint("rcexit", NULL))
1541                        {
1542                                changeret(recordduration, NULL);
1543                                break;
1544                        }
1545                        if(rcret == getrcconfigint("rcok", NULL))
1546                                break;
1547                }
1548
1549                if(recordduration->ret != NULL && ostrcmp(recordduration->ret, "0") != 0)
1550                        ret = atoi(recordduration->ret);
1551
1552                delownerrc(recordduration);
1553                clearscreen(recordduration);
1554
1555                return ret;
1556}
1557
1558void screenrecordstop()
1559{
1560        char* tmpstr = NULL;
1561        struct service* servicenode = service;
1562        struct menulist* mlist = NULL, *mbox = NULL, *tmpmbox = NULL;
1563
1564        while(servicenode != NULL)
1565        {
1566                if((servicenode->type == RECORDDIRECT || servicenode->type == RECORDTIMER) && servicenode->recname != NULL)
1567                {
1568                        tmpstr = ostrcat(tmpstr, _("stop"), 1, 0);
1569                        tmpstr = ostrcat(tmpstr, " (", 1, 0);
1570                        tmpstr = ostrcat(tmpstr, servicenode->recname, 1, 0);
1571                        tmpstr = ostrcat(tmpstr, ")", 1, 0);
1572                       
1573                        tmpmbox = addmenulist(&mlist, tmpstr, NULL, NULL, 0, 0);
1574                        free(tmpstr); tmpstr = NULL;
1575                        if(tmpmbox != NULL)
1576                        {
1577                                tmpmbox->param = ostrcat(tmpmbox->param, _("stop"), 1, 0);
1578                                tmpmbox->param = ostrcat(tmpmbox->param, " (", 1, 0);
1579                                tmpmbox->param = ostrcat(tmpmbox->param, servicenode->recname, 1, 0);
1580                                tmpmbox->param = ostrcat(tmpmbox->param, ")", 1, 0);
1581                        }
1582                }
1583                servicenode = servicenode->next;
1584        }
1585
1586        mbox = menulistbox(mlist, "recordlist", _("Record"), NULL, NULL, NULL, 0, 0);
1587       
1588        if(mbox != NULL && mbox->param != NULL && ostrstr(mbox->param, _("stop")) == mbox->param)
1589        {
1590                servicenode = getrecordbyname(mbox->param, RECORDDIRECT);
1591                if(servicenode != NULL)
1592                        servicenode->recendtime = 2;
1593                else
1594                {
1595                        servicenode = getrecordbyname(mbox->param, RECORDTIMER);
1596                        if(servicenode != NULL)
1597                                servicenode->recendtime = 2;
1598                }
1599        }
1600       
1601        freemenulist(mlist, 1); mlist = NULL;
1602}
1603
1604void screenrecorddirect()
1605{
1606        char* tmpstr = NULL;
1607        int ret = 0, ret1 = 0, newstart = 0;
1608        struct service* servicenode = service;
1609        struct epg* epgnode = NULL;
1610        struct menulist* mlist = NULL, *mbox = NULL, *tmpmbox = NULL;
1611        struct stimerthread *recthumbfirstthread = NULL;
1612
1613        while(servicenode != NULL)
1614        {
1615                if(servicenode->type == RECORDDIRECT && servicenode->recname != NULL)
1616                {
1617                        tmpstr = ostrcat(tmpstr, _("stop"), 1, 0);
1618                        tmpstr = ostrcat(tmpstr, " (", 1, 0);
1619                        tmpstr = ostrcat(tmpstr, servicenode->recname, 1, 0);
1620                        tmpstr = ostrcat(tmpstr, ")", 1, 0);
1621                       
1622                        tmpmbox = addmenulist(&mlist, tmpstr, NULL, NULL, 0, 0);
1623                        free(tmpstr); tmpstr = NULL;
1624                        if(tmpmbox != NULL)
1625                        {
1626                                tmpmbox->param = ostrcat(tmpmbox->param, _("stop"), 1, 0);
1627                                tmpmbox->param = ostrcat(tmpmbox->param, " (", 1, 0);
1628                                tmpmbox->param = ostrcat(tmpmbox->param, servicenode->recname, 1, 0);
1629                                tmpmbox->param = ostrcat(tmpmbox->param, ")", 1, 0);
1630                        }
1631                       
1632                        tmpstr = ostrcat(tmpstr, _("change"), 1, 0);
1633                        tmpstr = ostrcat(tmpstr, " (", 1, 0);
1634                        tmpstr = ostrcat(tmpstr, servicenode->recname, 1, 0);
1635                        tmpstr = ostrcat(tmpstr, ")", 1, 0);
1636                       
1637                        tmpmbox = addmenulist(&mlist, tmpstr, NULL, NULL, 0, 0);
1638                        free(tmpstr); tmpstr = NULL;
1639                        if(tmpmbox != NULL)
1640                        {
1641                                tmpmbox->param = ostrcat(tmpmbox->param, _("change"), 1, 0);
1642                                tmpmbox->param = ostrcat(tmpmbox->param, " (", 1, 0);
1643                                tmpmbox->param = ostrcat(tmpmbox->param, servicenode->recname, 1, 0);
1644                                tmpmbox->param = ostrcat(tmpmbox->param, ")", 1, 0);
1645                        }
1646                }
1647                servicenode = servicenode->next;
1648        }
1649
1650                //65535 gleich HDMIIN
1651        if(status.aktservice->channel->serviceid != 65535)
1652                addmenulist(&mlist, _("add recording (stop after current event)"), NULL, NULL, 0, 0);
1653        addmenulist(&mlist, _("add recording (indefinitely)"), NULL, NULL, 0, 0);
1654        addmenulist(&mlist, _("add recording (enter duration)"), NULL, NULL, 0, 0);
1655
1656        mbox = menulistbox(mlist, "recordlist", _("Record"), NULL, NULL, NULL, 0, 0);
1657       
1658        if(mbox != NULL)
1659        {
1660                if(mbox->param != NULL && ostrstr(mbox->param, _("stop")) == mbox->param)
1661                {
1662                        servicenode = getrecordbyname(mbox->param, RECORDDIRECT);
1663                        if(servicenode != NULL)
1664                                servicenode->recendtime = 2;
1665                }
1666                if(mbox->param != NULL && ostrstr(mbox->param, _("change")) == mbox->param)
1667                {
1668                        servicenode = getrecordbyname(mbox->param, RECORDDIRECT);
1669                        if(servicenode != NULL)
1670                        {
1671                                int nextmin = 0;
1672                                epgnode = getepgbytime(servicenode->channel, time(NULL));
1673                                if(epgnode != NULL) epgnode = epgnode->next;
1674                                if(epgnode != NULL) nextmin = (epgnode->endtime - time(NULL)) / 60;
1675                                if(nextmin < 0) nextmin = 0;
1676                                ret1 = (servicenode->recendtime - time(NULL)) / 60;
1677                                ret1 = screenrecordduration(ret1, nextmin);
1678                                if(ret1 > 0)
1679                                        servicenode->recendtime = time(NULL) + (ret1 * 60);
1680                        }
1681                }
1682                if(ostrcmp(mbox->name, _("add recording (stop after current event)")) == 0)
1683                {
1684                        epgnode = getepgbytime(status.aktservice->channel, time(NULL) + 60);
1685#ifndef SIMULATE
1686                        if(epgnode != NULL && epgnode->endtime > time(NULL))
1687                                ret = recordstart(status.aktservice->channel, -1, 0, RECDIRECT, epgnode->endtime, NULL);
1688                        else
1689                                textbox(_("Message"), _("Can't get EPG time or EPG endtime not ok"), _("EXIT"), getrcconfigint("rcexit", NULL), NULL, 0, NULL, 0, NULL, 0, 800, 200, 0, 0);
1690#else
1691                        ret = recordstart(status.aktservice->channel, -1,  0, RECDIRECT, time(NULL) + 5, NULL);
1692#endif
1693                        newstart = 1;
1694                }
1695                if(ostrcmp(mbox->name, _("add recording (indefinitely)")) == 0)
1696                {
1697                        ret = recordstart(status.aktservice->channel, -1, 0, RECDIRECT, 0, NULL);
1698                        newstart = 1;
1699                }
1700                if(ostrcmp(mbox->name, _("add recording (enter duration)")) == 0)
1701                {
1702                        ret1 = screenrecordduration(0, 0);
1703
1704                        if(ret1 > 0)
1705                        {
1706                                ret = recordstart(status.aktservice->channel, -1, 0, RECDIRECT, time(NULL) + (ret1 * 60), NULL);
1707                                newstart = 1;
1708                        }
1709                }
1710
1711                recordcheckret(NULL, ret, 6);
1712                if(ret == 0 && newstart == 1)
1713                {
1714                        textbox(_("Message"), _("Record started"), _("OK"), getrcconfigint("rcok", NULL), NULL, 0, NULL, 0, NULL, 0, 600, 200, 7, 0);
1715                        if(getconfigint("recordpicture", NULL) == 1)
1716                                recthumbfirstthread = addtimer(&createrecthumbfirstthread, START, 1000, 1, NULL, NULL, NULL);
1717                }
1718        }
1719        freemenulist(mlist, 1); mlist = NULL;
1720}
1721
1722#endif
Note: See TracBrowser for help on using the repository browser.