]> git.vomp.tv Git - vompclient.git/blob - playerradio.cc
Initial import
[vompclient.git] / playerradio.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 // this is a total copy from player but with video stuff taken out
22 // most of this isn't used because it's designed for recording playback
23
24
25 #include "playerradio.h"
26
27 PlayerRadio::PlayerRadio()
28 : afeedr(this, &stream)
29 {
30   initted = 0;
31
32   paused = 0;
33   playing = 0;
34   ffwd = 0;
35   fbwd = 0;
36   feedPosition = 0;
37   feedMode = MODE_NORMAL;
38
39   streamLength = 0;
40   // FIXME - this might need settings back to zero for new live play depending on what is done with it
41 }
42
43 PlayerRadio::~PlayerRadio()
44 {
45   if (initted) shutdown();
46 }
47
48 int PlayerRadio::init()
49 {
50   if (initted) return 0;
51
52   audio = Audio::getInstance();
53   stream.init(120000);
54   afeedr.init(audio->getFD());
55
56   audio->stop();
57
58   initted = 1;
59   return 1;
60 }
61
62 int PlayerRadio::shutdown()
63 {
64   if (!initted) return 0;
65   initted = 0;
66
67   Log::getInstance()->log("PlayerRadio", Log::DEBUG, "PlayerRadio shutdown...");
68
69   // copy of stop
70   if (playing)
71   {
72     playing = 0;
73     threadStop();
74     audio->stop();
75     afeedr.stop();
76     feedPosition = 0;
77   }
78
79   return 1;
80 }
81
82 int PlayerRadio::play()
83 {
84   if (!initted) return 0;
85
86   // If we are just paused, unpause!
87   if (paused)
88   {
89     togglePause();
90     return 1;
91   }
92
93   // If we are fast forwarding, set to normal
94   if (ffwd)
95   {
96     toggleFastForward();
97     return 1;
98   }
99
100   // If we are fast backwarding, set to normal
101   if (fbwd)
102   {
103     toggleFastBackward();
104     return 1;
105   }
106
107   // If we are already playing, bail // FIXME - resync?
108   if (playing)
109   {
110     Log::getInstance()->log("PlayerRadio", Log::DEBUG, "DOING RESYNC");
111
112     afeedr.stop();
113     audio->reset();
114     afeedr.start();
115
116     audio->play();
117     call();
118
119     return 1;
120   }
121
122   // Standard play start
123
124   audio->reset();
125
126 /*
127 // ------------------------ This one works, but doesn't allow any pre-buffering.
128   threadStart();
129   afeedr.start();
130   audio->play();
131   audio->sync();
132
133 // ------------------------ This one doesn't work, but it should, and would allow for prebuffering.
134 */
135
136   threadStart();
137     sleep(6);
138
139 //  struct timespec delay;
140 //  delay.tv_sec = 1;
141 //  delay.tv_nsec = 500000000;
142 //  nanosleep(&delay, NULL);
143
144   afeedr.start();
145   audio->play();
146 //  audio->sync();
147 // ------------------------------------------------------------------------------------------------
148
149   playing = 1;
150   return 1;
151 }
152
153 void PlayerRadio::stop()
154 {
155   if (!initted) return;
156   if (!playing) return;
157   playing = 0;
158
159   threadCancel();
160   audio->stop();
161   afeedr.stop();
162
163   feedPosition = 0;
164 }
165
166 void PlayerRadio::togglePause()
167 {
168   if (!initted) return;
169   if (!playing) return;
170
171   if (ffwd) toggleFastForward();
172   if (fbwd) toggleFastBackward();
173
174   if (paused)
175   {
176     audio->unPause();
177     paused = 0;
178   }
179   else
180   {
181     audio->pause();
182     paused = 1;
183   }
184 }
185
186 void PlayerRadio::setPosition(ULLONG position)
187 {
188   feedPosition = position;
189 }
190
191 void PlayerRadio::setLength(ULLONG length)
192 {
193   streamLength = length;
194   Log::getInstance()->log("PlayerRadio", Log::DEBUG, "PlayerRadio has received length of %llu", streamLength);
195 }
196
197 void PlayerRadio::skipForward()
198 {
199   // skip forward 1 minute
200   Log::getInstance()->log("PlayerRadio", Log::DEBUG, "SKIP FORWARD 1 MINUTE");
201
202   if (paused) togglePause();
203
204   threadStop();
205   afeedr.stop();
206   audio->stop();
207   audio->reset();
208   audio->doMuting();  // ???
209   feedPosition += 30000000;
210   afeedr.start();
211   threadStart();
212   audio->play();
213 }
214
215 void PlayerRadio::skipBackward()
216 {
217   // skip forward 1 minute
218   Log::getInstance()->log("PlayerRadio", Log::DEBUG, "SKIP BACKWARD 1 MINUTE");
219
220   if (paused) togglePause();
221
222   threadStop();
223   afeedr.stop();
224   audio->stop();
225   audio->reset();
226   audio->doMuting(); // ???
227   if (feedPosition > 30000000) feedPosition -= 30000000;
228   afeedr.start();
229   threadStart();
230   audio->play();
231 }
232
233 void PlayerRadio::toggleFastForward()
234 {
235   if (!initted) return;
236   if (!playing) return;
237
238   if (paused) togglePause();
239   if (fbwd) toggleFastBackward();
240
241   if (ffwd)
242   {
243     ffwd = 0;
244 //    afeedr.enable();
245     audio->reset();
246     audio->systemMuteOff();
247   }
248   else
249   {
250     ffwd = 1;
251 //    afeedr.disable();
252     audio->systemMuteOn();
253   }
254 }
255
256 void PlayerRadio::toggleFastBackward()
257 {
258   if (!initted) return;
259   if (!playing) return;
260
261   if (paused) togglePause();
262   if (ffwd) toggleFastForward();
263
264   if (fbwd)
265   {
266     fbwd = 0;
267 //    afeedr.enable();
268     audio->systemMuteOff();
269
270 //    threadStop();
271     feedMode = MODE_NORMAL;
272 //    threadStart();
273   }
274   else
275   {
276     fbwd = 1;
277 //    afeedr.disable();
278     audio->systemMuteOn();
279
280     threadStop();
281     feedMode = MODE_BACKWARDS;
282     threadStart();
283   }
284 }
285
286 void PlayerRadio::jumpToPercent(int percent)
287 {
288   threadStop();
289   afeedr.stop();
290   audio->stop();
291   audio->reset();
292   feedPosition = streamLength * percent / 100;
293   afeedr.start();
294   threadStart();
295   audio->play();
296   audio->sync();
297 }
298
299
300 void PlayerRadio::call()
301 {
302   threadSignalNoLock();
303 }
304
305 // Feed thread
306
307 void PlayerRadio::threadMethod()
308 {
309   UCHAR buf[blockSize];
310   int thisRead;
311   int writeLength;
312   int thisWrite;
313
314   VDR* vdr = VDR::getInstance();
315
316   int askFor;
317   while(1)
318   {
319     thisRead = 0;
320     writeLength = 0;
321     thisWrite = 0;
322
323     threadCheckExit();
324
325     // a bit hackey. this needs to be split to live and rec players
326     if (streamLength && (feedPosition >= streamLength)) break;
327     askFor = blockSize;
328     if (streamLength && ((feedPosition + blockSize) > streamLength))
329     {
330       askFor = streamLength - feedPosition;
331     }
332     thisRead = vdr->getBlock(buf, feedPosition, askFor);
333
334     if (feedMode == MODE_NORMAL)
335     {
336       feedPosition += thisRead;
337     }
338     else if (feedMode == MODE_BACKWARDS)
339     {
340       if (feedPosition >= 100000)
341       {
342         feedPosition -= 100000;
343       }
344       else
345       {
346         // got to the start of the recording.. revert to play mode? how?
347         feedPosition += thisRead;
348       }
349     }
350
351     threadCheckExit();
352
353     while(writeLength < thisRead)
354     {
355       thisWrite = stream.put(buf + writeLength, thisRead - writeLength);
356       writeLength += thisWrite;
357
358       if (!thisWrite)
359       {
360         Log::getInstance()->log("Player", Log::DEBUG, "RADIO OUTPUT STREAM FULL!!!");
361         // stream is full and cant take anymore
362         threadWaitForSignal();
363         Log::getInstance()->log("Player", Log::DEBUG, "BACK FROM WAIT");
364       }
365
366       threadCheckExit();
367     }
368
369     Log::getInstance()->log("PlayerRadio", Log::DEBUG, "Written audio");
370
371   }
372 }