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