]> git.vomp.tv Git - vompclient-marten.git/blob - player.cc
Initial import
[vompclient-marten.git] / player.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 #include "player.h"
22
23 Player::Player(MessageQueue* messageQueue)
24 : vfeed(this), afeed(this)
25 {
26   initted = 0;
27   commandMessageQueue = messageQueue;
28
29   paused = 0;
30   playing = 0;
31   ffwd = 0;
32   fbwd = 0;
33   feedPosition = 0;
34   feedMode = MODE_NORMAL;
35
36   streamLength = 0;
37   // FIXME - this might need settings back to zero for new live play depending on what is done with it
38 }
39
40 Player::~Player()
41 {
42   if (initted) shutdown();
43 }
44
45 int Player::init()
46 {
47   if (initted) return 0;
48
49   video = Video::getInstance();
50   audio = Audio::getInstance();
51
52   if (demuxer.init()) // inverted
53   {
54     Log::getInstance()->log("Player", Log::ERR, "Demuxer failed to init");
55     shutdown();
56     return 0;
57   }
58
59   vfeed.init(video->getFD());
60   afeed.init(audio->getFD());
61
62   video->stop();
63   video->blank();
64   audio->stop();
65
66   startup = 0;
67   initted = 1;
68   return 1;
69 }
70
71 int Player::shutdown()
72 {
73   if (!initted) return 0;
74   initted = 0;
75
76   Log::getInstance()->log("Player", Log::DEBUG, "Player shutdown...");
77
78   // copy of stop
79   if (playing)
80   {
81     playing = 0;
82     threadStop();
83     video->stop();
84     video->blank();
85     audio->stop();
86     vfeed.stop();
87     afeed.stop();
88     video->reset();
89     demuxer.reset();
90     feedPosition = 0;
91   }
92
93   return 1;
94 }
95
96 int Player::play()
97 {
98   if (!initted) return 0;
99
100   // If we are just paused, unpause!
101   if (paused)
102   {
103     togglePause();
104     return 1;
105   }
106
107   // If we are fast forwarding, set to normal
108   if (ffwd)
109   {
110     toggleFastForward();
111     return 1;
112   }
113
114   // If we are fast backwarding, set to normal
115   if (fbwd)
116   {
117     toggleFastBackward();
118     return 1;
119   }
120
121   // If we are already playing, bail // FIXME - resync?
122   if (playing)
123   {
124     Log::getInstance()->log("Player", Log::DEBUG, "DOING RESYNC");
125
126     vfeed.stop();
127     afeed.stop();
128     video->reset();
129     audio->reset();
130     demuxer.flush();
131     demuxer.seek();
132     vfeed.start();
133     afeed.start();
134
135
136     video->play();
137     audio->play();
138     video->sync();
139     audio->sync();
140     call();
141
142     return 1;
143   }
144
145   // Standard play start
146
147   audio->reset();
148   video->reset();
149   demuxer.reset();
150   startup = 1;
151
152 // ------------------------ This one works, but doesn't allow any pre-buffering.
153   threadStart();
154   vfeed.start();
155   afeed.start();
156   video->play();
157   audio->play();
158   video->sync();
159   audio->sync();
160 // ------------------------ This one doesn't work, but it should, and would allow for prebuffering.
161
162 /*
163
164   threadStart();
165   sleep(2);
166
167 //  struct timespec delay;
168 //  delay.tv_sec = 1;
169 //  delay.tv_nsec = 500000000;
170 //  nanosleep(&delay, NULL);
171
172   vfeed.start();
173   afeed.start();
174   video->play();
175   audio->play();
176   video->sync();
177   audio->sync();
178 */
179 // ------------------------------------------------------------------------------------------------
180
181   playing = 1;
182   return 1;
183 }
184
185 void Player::stop()
186 {
187   if (!initted) return;
188   if (!playing) return;
189
190   if (ffwd || fbwd)
191   {
192     ffwd = 0;
193     fbwd = 0;
194     afeed.enable();
195     video->unFastForward();
196     audio->systemMuteOff();
197     feedMode = MODE_NORMAL;
198   }
199
200   playing = 0;
201
202   threadStop();
203   video->stop();
204   video->blank();
205   audio->stop();
206   vfeed.stop();
207   afeed.stop();
208   video->reset();
209   demuxer.reset();
210
211   feedPosition = 0;
212 }
213
214 void Player::togglePause()
215 {
216   if (!initted) return;
217   if (!playing) return;
218
219   if (ffwd) toggleFastForward();
220   if (fbwd) toggleFastBackward();
221
222   if (paused)
223   {
224     video->unPause();
225     audio->unPause();
226     paused = 0;
227   }
228   else
229   {
230     video->pause();
231     audio->pause();
232     paused = 1;
233   }
234 }
235
236 void Player::test()
237 {
238   Log::getInstance()->log("Player", Log::DEBUG, "PLAYER TEST");
239
240   video->test();
241
242 //  static int flipflop = 0;
243
244 //  if (flipflop) video->setAspectRatio(Video::ASPECT16X9);
245 //  else video->setAspectRatio(Video::ASPECT4X3);
246
247 //  flipflop = !flipflop;
248
249 }
250
251 void Player::test2()
252 {
253   Log::getInstance()->log("Player", Log::DEBUG, "PLAYER TEST");
254
255   video->test2();
256 }
257
258 void Player::setPosition(ULLONG position)
259 {
260   feedPosition = position;
261 }
262
263 void Player::setLength(ULLONG length)
264 {
265   streamLength = length;
266   Log::getInstance()->log("Player", Log::DEBUG, "Player has received length of %llu", streamLength);
267 }
268
269 void Player::skipForward(int seconds)
270 {
271   // skip forward 1 minute
272   Log::getInstance()->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
273
274   if (paused) togglePause();
275
276   ULLONG moveBy = seconds * 500000;
277
278   threadStop();
279   vfeed.stop();
280   afeed.stop();
281   video->stop();
282   video->reset();
283   audio->reset();
284   audio->doMuting();  // ???
285   demuxer.flush();
286   feedPosition += moveBy;
287
288   printf("Audio test %i\n", audio->test());
289
290   vfeed.start();
291   afeed.start();
292   threadStart();
293   video->sync();
294   audio->sync();
295   video->play();
296   audio->play();
297
298 }
299
300 void Player::skipBackward(int seconds)
301 {
302   // skip forward 1 minute
303   Log::getInstance()->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
304
305   if (paused) togglePause();
306
307   ULLONG moveBy = seconds * 500000;
308
309   threadStop();
310   vfeed.stop();
311   afeed.stop();
312   video->stop();
313   audio->stop();
314   video->reset();
315   audio->reset();
316   audio->doMuting(); // ???
317   demuxer.flush();
318   if (feedPosition > moveBy) feedPosition -= moveBy;
319   vfeed.start();
320   afeed.start();
321   threadStart();
322   video->play();
323   audio->play();
324   video->sync();
325   audio->sync();
326 }
327
328 void Player::toggleFastForward()
329 {
330   if (!initted) return;
331   if (!playing) return;
332
333   if (paused) togglePause();
334   if (fbwd) toggleFastBackward();
335
336   if (ffwd)
337   {
338     ffwd = 0;
339     afeed.enable();
340     video->unFastForward();
341     audio->reset();
342     video->sync();
343     audio->sync();
344     audio->systemMuteOff();
345   }
346   else
347   {
348     ffwd = 1;
349     afeed.disable();
350     audio->systemMuteOn();
351     video->fastForward();
352   }
353 }
354
355 void Player::toggleFastBackward()
356 {
357   if (!initted) return;
358   if (!playing) return;
359
360   if (paused) togglePause();
361   if (ffwd) toggleFastForward();
362
363   if (fbwd)
364   {
365     fbwd = 0;
366     afeed.enable();
367     audio->systemMuteOff();
368
369 //    threadStop();
370     feedMode = MODE_NORMAL;
371 //    threadStart();
372   }
373   else
374   {
375     fbwd = 1;
376     afeed.disable();
377     audio->systemMuteOn();
378
379     threadStop();
380     feedMode = MODE_BACKWARDS;
381     video->reset();
382     video->play();
383     demuxer.flush();
384     threadStart();
385   }
386 }
387
388 void Player::jumpToPercent(int percent)
389 {
390   threadStop();
391   vfeed.stop();
392   afeed.stop();
393   video->stop();
394   audio->stop();
395   video->reset();
396   audio->reset();
397   demuxer.flush();
398   demuxer.seek();
399   feedPosition = streamLength * percent / 100;
400   vfeed.start();
401   afeed.start();
402   threadStart();
403   video->play();
404   audio->play();
405   video->sync();
406   audio->sync();
407 }
408
409
410 void Player::call()
411 {
412   threadSignalNoLock();
413 }
414
415 // Feed thread
416
417 void Player::threadMethod()
418 {
419   UCHAR buf[blockSize];
420   int thisRead;
421   int writeLength;
422   int thisWrite;
423
424   VDR* vdr = VDR::getInstance();
425
426   int askFor;
427   while(1)
428   {
429     thisRead = 0;
430     writeLength = 0;
431     thisWrite = 0;
432
433     threadCheckExit();
434
435     // a bit hackey. this needs to be split to live and rec players
436     if (streamLength && (feedPosition >= streamLength)) break;
437     askFor = blockSize;
438     if (streamLength && ((feedPosition + blockSize) > streamLength))
439     {
440       askFor = streamLength - feedPosition;
441     }
442     thisRead = vdr->getBlock(buf, feedPosition, askFor);
443     if (startup)
444     {
445       int a_stream = demuxer.scan(buf, thisRead);
446       demuxer.setAudioStream(a_stream);
447       Log::getInstance()->log("Player", Log::DEBUG, "Startup Audio stream chosen %x", a_stream);
448       startup = 0;
449     }
450
451     if (feedMode == MODE_NORMAL)
452     {
453       feedPosition += thisRead;
454     }
455     else if (feedMode == MODE_BACKWARDS)
456     {
457       if (feedPosition >= 100000)
458       {
459         feedPosition -= 100000;
460         demuxer.seek();
461       }
462       else
463       {
464         // got to the start of the recording.. revert to play mode? how?
465         feedPosition += thisRead;
466       }
467     }
468
469     threadCheckExit();
470
471     while(writeLength < thisRead)
472     {
473       thisWrite = demuxer.put(buf + writeLength, thisRead - writeLength);
474       writeLength += thisWrite;
475
476       if (!thisWrite)
477       {
478         Log::getInstance()->log("Player", Log::DEBUG, "DEMUXER FULL!!!");
479         // demuxer is full and cant take anymore
480         threadWaitForSignal();
481         Log::getInstance()->log("Player", Log::DEBUG, "BACK FROM WAIT");
482       }
483
484       threadCheckExit();
485     }
486   }
487
488   // end of recording
489   Log::getInstance()->log("Player", Log::DEBUG, "Recording playback ends");
490   Message* m = new Message();
491   m->message = Message::STOP_PLAYBACK;
492   Log::getInstance()->log("Player", Log::DEBUG, "Posting message...");
493   commandMessageQueue->postMessage(m);
494   Log::getInstance()->log("Player", Log::DEBUG, "Message posted...");
495
496
497 }