experimental PVR commit support
[vuplus_dvbapp] / lib / base / filepush.cpp
1 #include <config.h>
2 #include <lib/base/filepush.h>
3 #include <lib/base/eerror.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <sys/ioctl.h>
7
8 #define PVR_COMMIT 1
9
10 eFilePushThread::eFilePushThread(): m_messagepump(eApp, 0)
11 {
12         m_stop = 0;
13         flush();
14         enablePVRCommit(0);
15         CONNECT(m_messagepump.recv_msg, eFilePushThread::recvEvent);
16 }
17
18 static void signal_handler(int x)
19 {
20 }
21
22 void eFilePushThread::thread()
23 {
24         off_t dest_pos = 0;
25         
26         int already_empty = 0;
27         eDebug("FILEPUSH THREAD START");
28                 // this is a race. FIXME.
29         
30                 /* we set the signal to not restart syscalls, so we can detect our signal. */
31         struct sigaction act;
32         act.sa_handler = signal_handler; // no, SIG_IGN doesn't do it. we want to receive the -EINTR
33         act.sa_flags = 0;
34         sigaction(SIGUSR1, &act, 0);
35         
36         dest_pos = lseek(m_fd_dest, 0, SEEK_CUR);
37                 /* m_stop must be evaluated after each syscall. */
38         while (!m_stop)
39         {
40                         /* first try flushing the bufptr */
41                 if (m_buf_start != m_buf_end)
42                 {
43                                 // TODO: take care of boundaries.
44                         int w = write(m_fd_dest, m_buffer + m_buf_start, m_buf_end - m_buf_start);
45 //                      eDebug("wrote %d bytes", w);
46                         if (w <= 0)
47                         {
48                                 if (errno == -EINTR)
49                                         continue;
50                                 eDebug("eFilePushThread *write error* (%m) - not yet handled");
51                                 // ... we would stop the thread
52                         }
53
54                                 /* this should flush all written pages to disk. */
55                         posix_fadvise(m_fd_dest, dest_pos, w, POSIX_FADV_DONTNEED);
56
57                         dest_pos += w;
58 //                      printf("FILEPUSH: wrote %d bytes\n", w);
59                         m_buf_start += w;
60                         continue;
61                 }
62                         
63                         /* now fill our buffer. */
64                 m_buf_start = 0;
65                 m_buf_end = read(m_fd_source, m_buffer, sizeof(m_buffer));
66                 if (m_buf_end < 0)
67                 {
68                         m_buf_end = 0;
69                         if (errno == EINTR)
70                                 continue;
71                         eDebug("eFilePushThread *read error* - not yet handled");
72                 }
73                 if (m_buf_end == 0)
74                 {
75                                 /* on EOF, try COMMITting once. */
76                         if (m_send_pvr_commit && !already_empty)
77                         {
78                                 eDebug("sending PVR commit");
79                                 already_empty = 1;
80                                 if (::ioctl(m_fd_dest, PVR_COMMIT) == EINTR)
81                                         continue;
82                                 eDebug("commit done");
83                                                 /* well check again */
84                                 continue;
85                         }
86                         sendEvent(evtEOF);
87
88 #if 0
89                         eDebug("FILEPUSH: end-of-file! (currently unhandled)");
90                         if (!lseek(m_fd_source, 0, SEEK_SET))
91                         {
92                                 eDebug("(looping)");
93                                 continue;
94                         }
95 #endif
96                         break;
97                 } else
98                         already_empty = 0;
99 //              printf("FILEPUSH: read %d bytes\n", m_buf_end);
100         }
101         
102         eDebug("FILEPUSH THREAD STOP");
103 }
104
105 void eFilePushThread::start(int fd_source, int fd_dest)
106 {
107         m_fd_source = fd_source;
108         m_fd_dest = fd_dest;
109         resume();
110 }
111
112 void eFilePushThread::stop()
113 {
114         m_stop = 1;
115         sendSignal(SIGUSR1);
116         kill();
117 }
118
119 void eFilePushThread::pause()
120 {
121         stop();
122 }
123
124 void eFilePushThread::seek(int whence, off_t where)
125 {
126         ::lseek(m_fd_source, where, whence);
127 }
128
129 void eFilePushThread::resume()
130 {
131         m_stop = 0;
132         run();
133 }
134
135 void eFilePushThread::flush()
136 {
137         m_buf_start = m_buf_end = 0;
138 }
139
140 void eFilePushThread::enablePVRCommit(int s)
141 {
142         m_send_pvr_commit = s;
143 }
144
145 void eFilePushThread::sendEvent(int evt)
146 {
147         m_messagepump.send(evt);
148 }
149
150 void eFilePushThread::recvEvent(const int &evt)
151 {
152         m_event(evt);
153 }