changed: paplayer shouldn't wait for audio buffers to end if it's been asked to stop...
[xbmc:xbmc-antiquated.git] / xbmc / cores / paplayer / paplayer_linux.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "stdafx.h"
23 #include "paplayer.h"
24 #include "CodecFactory.h"
25 #include "../../utils/GUIInfoManager.h"
26 #include "AudioContext.h"
27 #include "../../FileSystem/FileShoutcast.h"
28 #include "../../Application.h"
29 #include "FileItem.h"
30 #include "Settings.h"
31 #include "MusicInfoTag.h"
32 #include "../AudioRenderers/AudioRendererFactory.h"
33
34 #ifdef _LINUX
35 #define XBMC_SAMPLE_RATE 44100
36 #else
37 #define XBMC_SAMPLE_RATE 48000
38 #endif
39
40 #define VOLUME_FFWD_MUTE 900 // 9dB
41
42 #define FADE_TIME 2 * 2048.0f / XBMC_SAMPLE_RATE.0f      // 2 packets
43
44 #define TIME_TO_CACHE_NEXT_FILE 5000L         // 5 seconds
45 #define TIME_TO_CROSS_FADE      10000L        // 10 seconds
46
47 extern XFILE::CFileShoutcast* m_pShoutCastRipper;
48
49 // PAP: Psycho-acoustic Audio Player
50 // Supporting all open  audio codec standards.
51 // First one being nullsoft's nsv audio decoder format
52
53 PAPlayer::PAPlayer(IPlayerCallback& callback) : IPlayer(callback)
54 {
55   m_bIsPlaying = false;
56   m_bPaused = false;
57   m_cachingNextFile = false;
58   m_currentlyCrossFading = false;
59   m_bQueueFailed = false;
60
61   m_currentDecoder = 0;
62
63   m_iSpeed = 1;
64   m_SeekTime=-1;
65   m_IsFFwdRewding = false;
66
67   m_pAudioDecoder[0] = NULL;
68   m_pAudioDecoder[1] = NULL;
69   m_pcmBuffer[0] = NULL;
70   m_pcmBuffer[1] = NULL;
71   m_bufferPos[0] = 0;
72   m_bufferPos[1] = 0;
73
74   m_currentStream = 0;
75   m_packet[0][0].packet = NULL;
76   m_packet[1][0].packet = NULL;
77
78   m_bytesSentOut = 0;
79
80   m_BytesPerSecond = 0;
81   m_SampleRate = 0;
82   m_Channels = 0;
83   m_BitsPerSample = 0;
84
85   m_resampleAudio = false;
86
87   m_visBufferLength = 0;
88   m_pCallback = NULL;
89
90   m_forceFadeToNext = false;
91   m_CacheLevel = 0;
92   m_LastCacheLevelCheck = 0;
93
94   m_currentFile = new CFileItem;
95   m_nextFile = new CFileItem;
96 }
97
98 PAPlayer::~PAPlayer()
99 {
100   CloseFileInternal(true);
101   delete m_currentFile;
102   delete m_nextFile;
103 }
104
105
106 void PAPlayer::OnExit()
107 {
108
109 }
110
111 bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options)
112 {
113   if (m_currentlyCrossFading) CloseFileInternal(false); //user seems to be in a hurry
114
115   m_crossFading = g_guiSettings.GetInt("musicplayer.crossfade");
116   //no crossfading for cdda, cd-reading goes mad and no crossfading for last.fm doesn't like two connections
117   if (file.IsCDDA() || file.IsLastFM() || file.IsShoutCast() ) m_crossFading = 0;
118   if (m_crossFading && IsPlaying())
119   {
120     //do a short crossfade on trackskip
121     //set to max 2 seconds for these prev/next transitions
122     if (m_crossFading > 2) m_crossFading = 2;
123     //queue for crossfading
124     bool result = QueueNextFile(file, false);
125     if (result)
126     {
127       //crossfading value may be update by QueueNextFile when nr of channels changed
128       if (!m_crossFading) // swap to next track
129         m_decoder[m_currentDecoder].SetStatus(STATUS_ENDED);
130       else //force to fade to next track immediately
131         m_forceFadeToNext = true;
132     }
133     return result;
134   }
135
136   // normal opening of file, nothing playing or crossfading not enabled
137   // however no need to return to gui audio device
138   CloseFileInternal(false);
139
140   // always open the file using the current decoder
141   m_currentDecoder = 0;
142
143   if (!m_decoder[m_currentDecoder].Create(file, (__int64)(options.starttime * 1000), m_crossFading))
144     return false;
145
146   m_iSpeed = 1;
147   m_bPaused = false;
148   m_bStopPlaying = false;
149   ResetTime();
150   m_clock.SetSpeed(0);
151
152   CLog::Log(LOGINFO, "PAPlayer: Playing %s", file.m_strPath.c_str());
153
154   m_clock.SetClock((__int64)(options.starttime * 1000));
155
156   m_decoder[m_currentDecoder].GetDataFormat(&m_Channels, &m_SampleRate, &m_BitsPerSample);
157
158   if (!CreateStream(m_currentStream, m_Channels, m_SampleRate, m_BitsPerSample))
159   {
160     m_decoder[m_currentDecoder].Destroy();
161     CLog::Log(LOGERROR, "PAPlayer::Unable to create audio stream");
162   }
163
164   *m_currentFile = file;
165
166   if (ThreadHandle() == NULL)
167     Create();
168
169   m_startEvent.Set();
170
171   m_bIsPlaying = true;
172   m_cachingNextFile = false;
173   m_currentlyCrossFading = false;
174   m_forceFadeToNext = false;
175   m_bQueueFailed = false;
176
177   m_decoder[m_currentDecoder].Start();  // start playback
178   m_clock.SetSpeed(m_iSpeed);
179
180   return true;
181 }
182
183 void PAPlayer::UpdateCrossFadingTime(const CFileItem& file)
184 {
185   if ((m_crossFading = g_guiSettings.GetInt("musicplayer.crossfade")))
186   {
187     if (
188       m_crossFading &&
189       (
190         file.IsCDDA() ||
191         file.IsLastFM() ||
192         (
193           file.HasMusicInfoTag() && !g_guiSettings.GetBool("musicplayer.crossfadealbumtracks") &&
194           (m_currentFile->GetMusicInfoTag()->GetAlbum() != "") &&
195           (m_currentFile->GetMusicInfoTag()->GetAlbum() == file.GetMusicInfoTag()->GetAlbum()) &&
196           (m_currentFile->GetMusicInfoTag()->GetDiscNumber() == file.GetMusicInfoTag()->GetDiscNumber()) &&
197           (m_currentFile->GetMusicInfoTag()->GetTrackNumber() == file.GetMusicInfoTag()->GetTrackNumber() - 1)
198         )
199       )
200     )
201     {
202       m_crossFading = 0;
203     }
204   }
205 }
206
207 void PAPlayer::OnNothingToQueueNotify()
208 {
209   //nothing to queue, stop playing
210   m_bQueueFailed = true;
211 }
212
213 bool PAPlayer::QueueNextFile(const CFileItem &file)
214 {
215   return QueueNextFile(file, true);
216 }
217
218 bool PAPlayer::QueueNextFile(const CFileItem &file, bool checkCrossFading)
219 {
220   if (IsPaused())
221     Pause();
222
223   if (file.m_strPath == m_currentFile->m_strPath &&
224       file.m_lStartOffset > 0 &&
225       file.m_lStartOffset == m_currentFile->m_lEndOffset)
226   { // continuing on a .cue sheet item - return true to say we'll handle the transistion
227     *m_nextFile = file;
228     return true;
229   }
230
231   // check if we can handle this file at all
232   int decoder = 1 - m_currentDecoder;
233   __int64 seekOffset = (file.m_lStartOffset * 1000) / 75;
234   if (!m_decoder[decoder].Create(file, seekOffset, m_crossFading))
235   {
236     m_bQueueFailed = true;
237     return false;
238   }
239
240   // ok, we're good to go on queuing this one up
241   CLog::Log(LOGINFO, "PAPlayer: Queuing next file %s", file.m_strPath.c_str());
242
243   m_bQueueFailed = false;
244   if (checkCrossFading)
245   {
246     UpdateCrossFadingTime(file);
247   }
248
249   unsigned int channels, samplerate, bitspersample;
250   m_decoder[decoder].GetDataFormat(&channels, &samplerate, &bitspersample);
251
252   // check the number of channels isn't changing (else we can't do crossfading)
253   if (m_crossFading && m_decoder[m_currentDecoder].GetChannels() == channels)
254   { // crossfading - need to create a new stream
255     if (!CreateStream(1 - m_currentStream, channels, samplerate, bitspersample))
256     {
257       m_decoder[decoder].Destroy();
258       CLog::Log(LOGERROR, "PAPlayer::Unable to create audio stream");
259     }
260   }
261   else
262   { // no crossfading if nr of channels is not the same
263     m_crossFading = 0;
264   }
265
266   *m_nextFile = file;
267
268   return true;
269 }
270
271
272
273 bool PAPlayer::CloseFileInternal(bool bAudioDevice /*= true*/)
274 {
275   if (IsPaused())
276     Pause();
277
278   m_bStopPlaying = true;
279   m_bStop = true;
280
281   m_visBufferLength = 0;
282   StopThread();
283
284   // kill both our streams if we need to
285   for (int i = 0; i < 2; i++)
286   {
287     m_decoder[i].Destroy();
288     FreeStream(i);
289   }
290
291   m_currentFile->Reset();
292   m_nextFile->Reset();
293
294   if(bAudioDevice)
295     g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
296
297   return true;
298 }
299
300 void PAPlayer::FreeStream(int stream)
301 {
302   if (m_pAudioDecoder[stream])
303   {
304     DrainStream(stream);
305
306     delete m_pAudioDecoder[stream];
307     free(m_pcmBuffer[stream]);
308   }
309   m_pAudioDecoder[stream] = 0;
310
311   if (m_packet[stream][0].packet)
312     free(m_packet[stream][0].packet);
313
314   for (int i = 0; i < PACKET_COUNT; i++)
315   {
316     m_packet[stream][i].packet = NULL;
317   }
318
319   m_resampler[stream].DeInitialize();
320 }
321
322 void PAPlayer::DrainStream(int stream)
323 {
324   if(m_bStopPlaying)
325   {
326     m_pAudioDecoder[stream]->Stop();
327     return;
328   }
329
330   DWORD silence = m_pAudioDecoder[stream]->GetChunkLen() - m_bufferPos[stream] % m_pAudioDecoder[stream]->GetChunkLen(); 
331
332   if(silence > 0 && m_bufferPos[stream] > 0) 
333   { 
334     CLog::Log(LOGDEBUG, "PAPlayer: Drain - adding %d bytes of silence, real pcmdata size: %d, chunk size: %d", silence, m_bufferPos[stream], m_pAudioDecoder[stream]->GetChunkLen()); 
335     memset(m_pcmBuffer[stream] + m_bufferPos[stream], 0, silence); 
336     m_bufferPos[stream] += silence; 
337   }
338
339   DWORD added = 0;
340   while(m_bufferPos[stream] - added >= m_pAudioDecoder[stream]->GetChunkLen())
341   {
342     added += m_pAudioDecoder[stream]->AddPackets(m_pcmBuffer[stream] + added, m_bufferPos[stream] - added);
343     Sleep(1);
344   }
345   m_bufferPos[stream] = 0; 
346
347   m_pAudioDecoder[stream]->WaitCompletion();
348 }
349
350 bool PAPlayer::CreateStream(int num, int channels, int samplerate, int bitspersample, CStdString codec)
351 {
352   FreeStream(num);
353
354   if (channels <= 2 && g_advancedSettings.m_musicResample)
355     m_SampleRateOutput = g_advancedSettings.m_musicResample;
356   else
357     m_SampleRateOutput = samplerate;
358
359   m_BitsPerSampleOutput = 16;
360
361   m_BytesPerSecond = (m_BitsPerSampleOutput / 8)*m_SampleRateOutput*channels;
362
363   /* Open the device */
364   m_pAudioDecoder[num] = CAudioRendererFactory::Create(m_pCallback, channels, m_SampleRateOutput, m_BitsPerSampleOutput, false, codec.c_str(), true, false);
365
366   if (!m_pAudioDecoder[num]) return false;
367
368   m_pcmBuffer[num] = (unsigned char*)malloc((m_pAudioDecoder[num]->GetChunkLen() + PACKET_SIZE));
369   m_bufferPos[num] = 0;
370   m_latency[num]   = m_pAudioDecoder[num]->GetDelay();
371
372   m_packet[num][0].packet = (BYTE*)malloc(PACKET_SIZE * PACKET_COUNT);
373   for (int i = 1; i < PACKET_COUNT ; i++)
374     m_packet[num][i].packet = m_packet[num][i - 1].packet + PACKET_SIZE;
375
376   // create our resampler  // upsample to XBMC_SAMPLE_RATE, only do this for sources with 1 or 2 channels
377   m_resampler[num].InitConverter(samplerate, bitspersample, channels, m_SampleRateOutput, m_BitsPerSampleOutput, PACKET_SIZE);
378
379   // set initial volume
380   SetStreamVolume(num, g_stSettings.m_nVolumeLevel);
381
382   // TODO: How do we best handle the callback, given that our samplerate etc. may be
383   // changing at this point?
384
385   // fire off our init to our callback
386   if (m_pCallback)
387     m_pCallback->OnInitialize(channels, m_SampleRateOutput, m_BitsPerSampleOutput);
388
389   return true;
390 }
391
392 void PAPlayer::Pause()
393 {
394   CLog::Log(LOGDEBUG,"PAPlayer: pause m_bplaying: %d", m_bIsPlaying);
395   if (!m_bIsPlaying || !m_pAudioDecoder)
396   return ;
397
398   m_bPaused = !m_bPaused;
399
400   if (m_bPaused)
401   {
402     m_clock.SetSpeed(0);
403     if (m_pAudioDecoder[m_currentStream])
404       m_pAudioDecoder[m_currentStream]->Pause();
405
406     if (m_currentlyCrossFading && m_pAudioDecoder[1 - m_currentStream])
407       m_pAudioDecoder[1 - m_currentStream]->Pause();
408
409     CLog::Log(LOGDEBUG, "PAPlayer: Playback paused");
410   }
411   else
412   {
413     m_clock.SetSpeed(m_iSpeed);
414     if (m_pAudioDecoder[m_currentStream])
415       m_pAudioDecoder[m_currentStream]->Resume();
416
417     if (m_currentlyCrossFading && m_pAudioDecoder[1 - m_currentStream])
418       m_pAudioDecoder[1 - m_currentStream]->Resume();
419
420     FlushStreams();
421
422     CLog::Log(LOGDEBUG, "PAPlayer: Playback resumed");
423   }
424 }
425
426 void PAPlayer::SetVolume(long nVolume)
427 {
428   m_pAudioDecoder[m_currentStream]->SetCurrentVolume(nVolume);
429 }
430
431 void PAPlayer::SetDynamicRangeCompression(long drc)
432 {
433   // TODO: Add volume amplification
434   CLog::Log(LOGDEBUG,"PAPlayer::SetDynamicRangeCompression - drc: %lu", drc);
435 }
436
437 void PAPlayer::Process()
438 {
439   CLog::Log(LOGDEBUG, "PAPlayer: Thread started");
440   if (m_startEvent.WaitMSec(100))
441   {
442     m_startEvent.Reset();
443
444     m_callback.OnPlayBackStarted();
445
446     do
447     {
448       if (!m_bPaused)
449       {
450         if (!ProcessPAP())
451           break;
452       }
453       else
454       {
455         Sleep(100);
456       }
457     }
458     while (!m_bStopPlaying && m_bIsPlaying && !m_bStop);
459
460     CLog::Log(LOGINFO, "PAPlayer: End of playback reached");
461     m_bIsPlaying = false;
462     if (!m_bStopPlaying && !m_bStop)
463       m_callback.OnPlayBackEnded();
464     else
465       m_callback.OnPlayBackStopped();
466   }
467   CLog::Log(LOGDEBUG, "PAPlayer: Thread end");
468 }
469
470 void PAPlayer::ToFFRW(int iSpeed)
471 {
472   m_iSpeed = iSpeed;
473   m_clock.SetSpeed(iSpeed);
474 }
475
476 void PAPlayer::UpdateCacheLevel()
477 {
478   //check cachelevel every .5 seconds
479   if (m_LastCacheLevelCheck + 500 < GetTickCount())
480   {
481     ICodec* codec = m_decoder[m_currentDecoder].GetCodec();
482     if (codec)
483     {
484       m_CacheLevel = codec->GetCacheLevel();
485       m_LastCacheLevelCheck = GetTickCount();
486       //CLog::Log(LOGDEBUG,"Cachelevel: %i%%", m_CacheLevel);
487     }
488   }
489 }
490
491 bool PAPlayer::ProcessPAP()
492 {
493   /*
494    * Here's what we should be doing in each player loop:
495    *
496    * 1.  Run DoWork() on our audio device to actually output audio.
497    *
498    * 2.  Pass our current buffer to the audio device to see if it wants anything,
499    *     and if so, reduce our buffer size accordingly.
500    *
501    * 3.  Check whether we have space in our buffer for more data, and if so,
502    *     read some more in.
503    *
504    * 4.  Check for end of file and return false if we reach it.
505    *
506    * 5.  Perform any seeking and ffwd/rewding as necessary.
507    *
508    * 6.  If we don't do anything in 2...5, we can take a breather and break out for sleeping.
509    */
510   while (true)
511   {
512     if (m_bStop) return false;
513
514     // Check for .cue sheet item end
515     if (m_currentFile->m_lEndOffset && GetTime() >= GetTotalTime64())
516     {
517       CLog::Log(LOGINFO, "PAPlayer: Passed end of track in a .cue sheet item");
518       m_decoder[m_currentDecoder].SetStatus(STATUS_ENDED);
519     }
520
521     // check whether we need to send off our callbacks etc.
522     int status = m_decoder[m_currentDecoder].GetStatus();
523     if (status == STATUS_NO_FILE)
524       return false;
525
526     UpdateCacheLevel();
527
528     // check whether we should queue the next file up
529     if ((GetTotalTime64() > 0) && GetTotalTime64() - GetTime() < TIME_TO_CACHE_NEXT_FILE + m_crossFading * 1000L && !m_cachingNextFile)
530     { // request the next file from our application
531       m_callback.OnQueueNextItem();
532       m_cachingNextFile = true;
533     }
534
535     if (m_crossFading && m_decoder[0].GetChannels() == m_decoder[1].GetChannels())
536     {
537       if (((GetTotalTime64() - GetTime() < m_crossFading * 1000L) || (m_forceFadeToNext)) && !m_currentlyCrossFading)
538       { // request the next file from our application
539         if (m_decoder[1 - m_currentDecoder].GetStatus() == STATUS_QUEUED && m_pAudioDecoder[1 - m_currentStream])
540         {
541           m_currentlyCrossFading = true;
542           if (m_forceFadeToNext)
543           {
544             m_forceFadeToNext = false;
545             m_crossFadeLength = m_crossFading * 1000L;
546           }
547           else
548           {
549             m_crossFadeLength = GetTotalTime64() - GetTime();
550           }
551           m_currentDecoder = 1 - m_currentDecoder;
552           m_decoder[m_currentDecoder].Start();
553           m_currentStream = 1 - m_currentStream;
554           CLog::Log(LOGDEBUG, "Starting Crossfade - resuming stream %i", m_currentStream);
555
556           m_pAudioDecoder[m_currentStream]->Resume();
557
558           m_callback.OnPlayBackStarted();
559           ResetTime();
560           m_clock.SetClock(m_nextFile->m_lStartOffset * 1000 / 75);
561           *m_currentFile = *m_nextFile;
562           m_nextFile->Reset();
563           m_cachingNextFile = false;
564         }
565       }
566     }
567
568     // Check for EOF and queue the next track if applicable
569     if (m_decoder[m_currentDecoder].GetStatus() == STATUS_ENDED)
570     { // time to swap tracks
571       if (m_nextFile->m_strPath != m_currentFile->m_strPath ||
572           !m_nextFile->m_lStartOffset ||
573           m_nextFile->m_lStartOffset != m_currentFile->m_lEndOffset)
574       { // don't have a .cue sheet item
575         int nextstatus = m_decoder[1 - m_currentDecoder].GetStatus();
576         if (nextstatus == STATUS_QUEUED || nextstatus == STATUS_QUEUING || nextstatus == STATUS_PLAYING)
577         { // swap streams
578           CLog::Log(LOGDEBUG, "PAPlayer: Swapping tracks %i to %i", m_currentDecoder, 1-m_currentDecoder);
579           if (!m_crossFading || m_decoder[0].GetChannels() != m_decoder[1].GetChannels())
580           { // playing gapless (we use only the 1 output stream in this case)
581             int prefixAmount = m_decoder[m_currentDecoder].GetDataSize();
582             CLog::Log(LOGDEBUG, "PAPlayer::Prefixing %i samples of old data to new track for gapless playback", prefixAmount);
583             m_decoder[1 - m_currentDecoder].PrefixData(m_decoder[m_currentDecoder].GetData(prefixAmount), prefixAmount);
584             // check if we need to change the resampler (due to format change)
585             unsigned int channels, samplerate, bitspersample;
586             m_decoder[m_currentDecoder].GetDataFormat(&channels, &samplerate, &bitspersample);
587             unsigned int channels2, samplerate2, bitspersample2;
588             m_decoder[1 - m_currentDecoder].GetDataFormat(&channels2, &samplerate2, &bitspersample2);
589             // change of channels - reinitialize our speaker configuration
590             if (channels != channels2 || (g_advancedSettings.m_musicResample == 0 && (samplerate != samplerate2 || bitspersample != bitspersample2)))
591             {
592               CLog::Log(LOGINFO, "PAPlayer: Stream properties have changed, restarting stream");
593               FreeStream(m_currentStream);
594               if (!CreateStream(m_currentStream, channels2, samplerate2, bitspersample2))
595               {
596                 CLog::Log(LOGERROR, "PAPlayer: Error creating stream!");
597                 return false;
598               }
599               m_pAudioDecoder[m_currentStream]->Resume();
600             }
601             else if (samplerate != samplerate2 || bitspersample != bitspersample2)
602             {
603               CLog::Log(LOGINFO, "PAPlayer: Restarting resampler due to a change in data format");
604               m_resampler[m_currentStream].DeInitialize();
605               if (!m_resampler[m_currentStream].InitConverter(samplerate2, bitspersample2, channels2, g_advancedSettings.m_musicResample, 16, PACKET_SIZE))
606               {
607                 CLog::Log(LOGERROR, "PAPlayer: Error initializing resampler!");
608                 return false;
609               }
610             }
611             CLog::Log(LOGINFO, "PAPlayer: Starting new track");
612
613             m_decoder[m_currentDecoder].Destroy();
614             m_decoder[1 - m_currentDecoder].Start();
615             m_callback.OnPlayBackStarted();
616             ResetTime();
617             m_clock.SetClock(m_nextFile->m_lStartOffset * 1000 / 75);
618             *m_currentFile = *m_nextFile;
619             m_nextFile->Reset();
620             m_cachingNextFile = false;
621             m_currentDecoder = 1 - m_currentDecoder;
622           }
623           else
624           { // cross fading - shouldn't ever get here - if we do, return false
625             if (!m_currentlyCrossFading)
626             {
627               CLog::Log(LOGERROR, "End of file Reached before crossfading kicked in!");
628               return false;
629             }
630             else
631             {
632               CLog::Log(LOGINFO, "End of file reached before crossfading finished!");
633               return false;
634             }
635           }
636         }
637         else
638         {
639           if (GetTotalTime64() <= 0 && !m_bQueueFailed)
640           { //we did not know the duration so didn't queue the next song, try queueing it now
641             if (!m_cachingNextFile)
642             {// request the next file from our application
643               m_callback.OnQueueNextItem();
644               m_cachingNextFile = true;
645             }
646           }
647           else
648           {
649             // no track queued - return and get another one once we are finished
650             // with the current stream
651             WaitForStream();
652             return false;
653           }
654         }
655       }
656       else
657       {
658         // set the next track playing (.cue sheet)
659         m_decoder[m_currentDecoder].SetStatus(STATUS_PLAYING);
660         m_callback.OnPlayBackStarted();
661         ResetTime();
662         m_clock.SetClock(m_nextFile->m_lStartOffset * 1000 / 75);
663         *m_currentFile = *m_nextFile;
664         m_nextFile->Reset();
665         m_cachingNextFile = false;
666       }
667     }
668
669     // handle seeking and ffwd/rewding.
670     HandleSeeking();
671     if (!HandleFFwdRewd())
672     {
673       // need to skip to the next track - let's see if we already have another one
674       m_decoder[m_currentDecoder].SetStatus(STATUS_ENDED);
675       continue; // loop around to start the next track
676     }
677
678     if (!m_bPaused) {
679
680     // Let our decoding stream(s) do their thing
681     int retVal = m_decoder[m_currentDecoder].ReadSamples(PACKET_SIZE);
682     if (retVal == RET_ERROR)
683     {
684       m_decoder[m_currentDecoder].Destroy();
685       return false;
686     }
687
688     int retVal2 = m_decoder[1 - m_currentDecoder].ReadSamples(PACKET_SIZE);
689     if (retVal2 == RET_ERROR)
690     {
691       m_decoder[1 - m_currentDecoder].Destroy();
692     }
693
694     // if we're cross-fading, then we do this for both streams, otherwise
695     // we do it just for the one stream.
696     if (m_currentlyCrossFading)
697     {
698       if (GetTime() >= m_crossFadeLength)  // finished
699       {
700         CLog::Log(LOGDEBUG, "Finished Crossfading");
701         m_currentlyCrossFading = false;
702         SetStreamVolume(m_currentStream, g_stSettings.m_nVolumeLevel);
703         FreeStream(1 - m_currentStream);
704         m_decoder[1 - m_currentDecoder].Destroy();
705       }
706       else
707       {
708         float fraction = (float)(m_crossFadeLength - GetTime()) / (float)m_crossFadeLength - 0.5f;
709         // make sure we can take valid logs.
710         if (fraction > 0.499f) fraction = 0.499f;
711         if (fraction < -0.499f) fraction = -0.499f;
712         float volumeCurrent = 2000.0f * log10(0.5f - fraction);
713         float volumeNext = 2000.0f * log10(0.5f + fraction);
714         SetStreamVolume(m_currentStream, g_stSettings.m_nVolumeLevel + (int)volumeCurrent);
715         SetStreamVolume(1 - m_currentStream, g_stSettings.m_nVolumeLevel + (int)volumeNext);
716         if (AddPacketsToStream(1 - m_currentStream, m_decoder[1 - m_currentDecoder]))
717           retVal2 = RET_SUCCESS;
718       }
719     }
720
721        // add packets as necessary
722        if (AddPacketsToStream(m_currentStream, m_decoder[m_currentDecoder]))
723          retVal = RET_SUCCESS;
724
725        if (retVal == RET_SLEEP && retVal2 == RET_SLEEP)
726          Sleep(1);
727     }
728     else
729         Sleep(100);
730   }
731   return true;
732 }
733
734 void PAPlayer::ResetTime()
735 {
736   m_bytesSentOut = 0;
737   m_clock.ResetClock();
738 }
739
740 __int64 PAPlayer::GetTime()
741 {
742   return m_clock.GetTimeMS() - m_currentFile->m_lStartOffset * 1000 / 75;
743 }
744
745 __int64 PAPlayer::GetTotalTime64()
746 {
747   __int64 total = m_decoder[m_currentDecoder].TotalTime();
748   if (m_currentFile->m_lEndOffset)
749     total = m_currentFile->m_lEndOffset * 1000 / 75;
750   if (m_currentFile->m_lStartOffset)
751     total -= m_currentFile->m_lStartOffset * 1000 / 75;
752   return total;
753 }
754
755 int PAPlayer::GetTotalTime()
756 {
757   return (int)(GetTotalTime64()/1000);
758 }
759
760 int PAPlayer::GetCacheLevel() const
761 {
762   const ICodec* codec = m_decoder[m_currentDecoder].GetCodec();
763   if (codec)
764     return codec->GetCacheLevel();
765
766   return -1;
767 }
768
769 int PAPlayer::GetChannels()
770 {
771   ICodec* codec = m_decoder[m_currentDecoder].GetCodec();
772   if (codec)
773     return codec->m_Channels;
774   return 0;
775 }
776
777 int PAPlayer::GetBitsPerSample()
778 {
779   ICodec* codec = m_decoder[m_currentDecoder].GetCodec();
780   if (codec)
781     return codec->m_BitsPerSample;
782   return 0;
783 }
784
785 int PAPlayer::GetSampleRate()
786 {
787   ICodec* codec = m_decoder[m_currentDecoder].GetCodec();
788   if (codec)
789     return (int)((codec->m_SampleRate / 1000) + 0.5);
790   return 0;
791 }
792
793 CStdString PAPlayer::GetCodecName()
794 {
795   ICodec* codec = m_decoder[m_currentDecoder].GetCodec();
796   if (codec)
797     return codec->m_CodecName;
798   return "";
799 }
800
801 int PAPlayer::GetAudioBitrate()
802 {
803   ICodec* codec = m_decoder[m_currentDecoder].GetCodec();
804   if (codec)
805     return (int)((codec->m_Bitrate / 1000) + 0.5); // in kbits/s, rounded to the nearest int
806   return 0;
807 }
808
809 bool PAPlayer::CanSeek()
810 {
811   return ((m_decoder[m_currentDecoder].TotalTime() > 0) && m_decoder[m_currentDecoder].CanSeek());
812 }
813
814 void PAPlayer::Seek(bool bPlus, bool bLargeStep)
815 {
816   __int64 seek;
817   if (g_advancedSettings.m_musicUseTimeSeeking && GetTotalTime() > 2*g_advancedSettings.m_musicTimeSeekForwardBig)
818   {
819     if (bLargeStep)
820       seek = bPlus ? g_advancedSettings.m_musicTimeSeekForwardBig : g_advancedSettings.m_musicTimeSeekBackwardBig;
821     else
822       seek = bPlus ? g_advancedSettings.m_musicTimeSeekForward : g_advancedSettings.m_musicTimeSeekBackward;
823     seek *= 1000;
824     seek += GetTime();
825   }
826   else
827   {
828     float percent;
829     if (bLargeStep)
830       percent = bPlus ? (float)g_advancedSettings.m_musicPercentSeekForwardBig : (float)g_advancedSettings.m_musicPercentSeekBackwardBig;
831     else
832       percent = bPlus ? (float)g_advancedSettings.m_musicPercentSeekForward : (float)g_advancedSettings.m_musicPercentSeekBackward;
833     seek = (__int64)(GetTotalTime64()*(GetPercentage()+percent)/100);
834   }
835
836   SeekTime(seek);
837 }
838
839 void PAPlayer::SeekTime(__int64 iTime /*=0*/)
840 {
841   if (!CanSeek()) return;
842   if (m_currentFile->m_lStartOffset)
843     iTime += m_currentFile->m_lStartOffset * 1000 / 75;
844   m_SeekTime = iTime;
845   CLog::Log(LOGDEBUG, "PAPlayer::Seeking to time %f", 0.001f * m_SeekTime);
846 }
847
848 void PAPlayer::SeekPercentage(float fPercent /*=0*/)
849 {
850   if (fPercent < 0.0f) fPercent = 0.0f;
851   if (fPercent > 100.0f) fPercent = 100.0f;
852   SeekTime((__int64)(fPercent * 0.01f * (float)GetTotalTime64()));
853 }
854
855 float PAPlayer::GetPercentage()
856 {
857   float percent = (float)GetTime() * 100.0f / GetTotalTime64();
858   return percent;
859 }
860
861 void PAPlayer::HandleSeeking()
862 {
863   if (m_SeekTime != -1)
864   {
865     DWORD time = timeGetTime();
866     m_clock.SetClock(m_decoder[m_currentDecoder].Seek(m_SeekTime));
867     CLog::Log(LOGDEBUG, "Seek to time %f took %u ms",
868               0.001f * m_SeekTime, timeGetTime() - time);
869     FlushStreams();
870     m_SeekTime = -1;
871   }
872   g_infoManager.m_performingSeek = false;
873 }
874
875 void PAPlayer::FlushStreams()
876 {
877   m_bytesSentOut = 0;
878   for (int stream = 0; stream < 2; stream++)
879   {
880     if (m_pAudioDecoder[stream] && m_packet[stream])
881     {
882       m_pAudioDecoder[stream]->Stop();
883       m_pAudioDecoder[stream]->Resume();
884       m_bufferPos[stream] = 0;
885     }
886   }
887 }
888
889 bool PAPlayer::HandleFFwdRewd()
890 {
891   if (!m_IsFFwdRewding && m_iSpeed == 1)
892     return true;  // nothing to do
893   if (m_IsFFwdRewding && m_iSpeed == 1)
894   { // stop ffwd/rewd
895     m_IsFFwdRewding = false;
896     SetVolume(g_stSettings.m_nVolumeLevel);
897     m_clock.SetClock(m_decoder[m_currentDecoder].Seek(GetTime()));
898     FlushStreams();
899     return true;
900   }
901   // we're definitely fastforwarding or rewinding
902   int snippet = m_BytesPerSecond / 2;
903   if ( m_bytesSentOut >= snippet )
904   {
905     // Calculate time to seek to if we do FF/RW
906     __int64 time = GetTime();
907
908     // Is our offset inside the track range?
909     if (time >= 0 && time <= m_decoder[m_currentDecoder].TotalTime())
910     { // just set next position to read
911       m_IsFFwdRewding = true;
912       time += m_currentFile->m_lStartOffset * 1000 / 75;
913       m_clock.SetClock(m_decoder[m_currentDecoder].Seek(time));
914       FlushStreams();
915       SetVolume(g_stSettings.m_nVolumeLevel - VOLUME_FFWD_MUTE); // override xbmc mute
916     }
917     else if (time < 0)
918     { // ...disable seeking and start the track again
919       ToFFRW(1);
920       time = m_currentFile->m_lStartOffset * 1000 / 75;
921       m_clock.SetClock(m_decoder[m_currentDecoder].Seek(time));
922       FlushStreams();
923       SetVolume(g_stSettings.m_nVolumeLevel); // override xbmc mute
924     } // is our next position greater then the end sector...
925     else //if (time > m_codec->m_TotalTime)
926     {
927       // restore volume level so the next track isn't muted
928       SetVolume(g_stSettings.m_nVolumeLevel);
929       CLog::Log(LOGDEBUG, "PAPlayer: End of track reached while seeking");
930       return false;
931     }
932   }
933   return true;
934 }
935
936 void PAPlayer::SetStreamVolume(int stream, long nVolume)
937 {
938   m_pAudioDecoder[stream]->SetCurrentVolume(nVolume);
939 }
940
941 bool PAPlayer::AddPacketsToStream(int stream, CAudioDecoder &dec)
942 {
943   if (!m_pAudioDecoder[stream] || dec.GetStatus() == STATUS_NO_FILE)
944     return false;
945
946   bool ret = false;
947   int amount = m_resampler[stream].GetInputSamples();
948   if (amount > 0 && amount <= (int)dec.GetDataSize())
949   { // resampler wants more data - let's feed it
950     m_resampler[stream].PutFloatData((float *)dec.GetData(amount), amount);
951     ret = true;
952   }
953   else if (m_pAudioDecoder[stream]->GetChunkLen() > m_pAudioDecoder[stream]->GetSpace())
954   { // resampler probably have data but wait until we can send atleast one chunk
955     ret = false;
956   }
957   else if (m_resampler[stream].GetData(m_packet[stream][0].packet))
958   {
959     // got some data from our resampler - construct audio packet
960     m_packet[stream][0].length = PACKET_SIZE;
961     m_packet[stream][0].stream = stream;
962
963     unsigned char *pcmPtr = m_packet[stream][0].packet;
964     int len = m_packet[stream][0].length;
965     StreamCallback(&m_packet[stream][0]);
966
967     memcpy(m_pcmBuffer[stream]+m_bufferPos[stream], pcmPtr, len);
968     m_bufferPos[stream] += len;
969
970     while (m_bufferPos[stream] >= (int)m_pAudioDecoder[stream]->GetChunkLen())
971     {
972       int rtn = m_pAudioDecoder[stream]->AddPackets(m_pcmBuffer[stream], m_bufferPos[stream]);
973       m_bufferPos[stream] -= rtn;
974       memcpy(m_pcmBuffer[stream], m_pcmBuffer[stream] + rtn, m_bufferPos[stream]);
975     }
976
977     // something done
978     ret = true;
979   }
980
981   return ret;
982 }
983
984 bool PAPlayer::FindFreePacket( int stream, DWORD* pdwPacket )
985 {
986   return true;
987 }
988
989 void PAPlayer::RegisterAudioCallback(IAudioCallback *pCallback)
990 {
991   m_pCallback = pCallback;
992   if (m_pCallback)
993     m_pCallback->OnInitialize(m_Channels, m_SampleRateOutput, m_BitsPerSampleOutput);
994 }
995
996 void PAPlayer::UnRegisterAudioCallback()
997 {
998   m_pCallback = NULL;
999 }
1000
1001 void PAPlayer::DoAudioWork()
1002 {
1003   if (m_pCallback && m_visBufferLength)
1004   {
1005     m_pCallback->OnAudioData((BYTE*)m_visBuffer, m_visBufferLength);
1006     m_visBufferLength = 0;
1007   }
1008 }
1009
1010 void PAPlayer::StreamCallback( LPVOID pPacketContext )
1011 {
1012   AudioPacket *pkt = (AudioPacket *)pPacketContext;
1013
1014
1015   // only process from the current stream (if we're crossfading for instance)
1016   if (pkt->stream != m_currentStream)
1017     return;
1018
1019   m_bytesSentOut += pkt->length;
1020
1021   if (m_pCallback)
1022   { // copy into our visualisation buffer.
1023     // can't use a memcpy() here due to the context (will crash otherwise)
1024     memcpy((short*)m_visBuffer, pkt->packet, pkt->length);
1025     m_visBufferLength = pkt->length;
1026   }
1027 }
1028
1029 void CALLBACK StaticStreamCallback( VOID* pStreamContext, VOID* pPacketContext, DWORD dwStatus )
1030 {
1031   PAPlayer* pPlayer = (PAPlayer*)pStreamContext;
1032   pPlayer->StreamCallback(pPacketContext);
1033 }
1034
1035 bool PAPlayer::HandlesType(const CStdString &type)
1036 {
1037   ICodec* codec=CodecFactory::CreateCodec(type);
1038
1039   if (codec && codec->CanInit())
1040   {
1041     delete codec;
1042     return true;
1043   }
1044   if (codec)
1045     delete codec;
1046
1047   return false;
1048 }
1049
1050 // Skip to next track/item inside the current media (if supported).
1051 bool PAPlayer::SkipNext()
1052 {
1053   if (m_decoder[m_currentDecoder].GetCodec() && m_decoder[m_currentDecoder].GetCodec()->SkipNext())
1054   {
1055     return true;
1056   }
1057   return false;
1058 }
1059
1060 bool PAPlayer::CanRecord()
1061 {
1062   if (!m_pShoutCastRipper) return false;
1063   return m_pShoutCastRipper->CanRecord();
1064 }
1065
1066 bool PAPlayer::IsRecording()
1067 {
1068   if (!m_pShoutCastRipper) return false;
1069   return m_pShoutCastRipper->IsRecording();
1070 }
1071
1072 bool PAPlayer::Record(bool bOnOff)
1073 {
1074   if (!m_pShoutCastRipper) return false;
1075   if (bOnOff && IsRecording()) return true;
1076   if (bOnOff == false && IsRecording() == false) return true;
1077   if (bOnOff)
1078     return m_pShoutCastRipper->Record();
1079
1080   m_pShoutCastRipper->StopRecording();
1081   return true;
1082 }
1083
1084 void PAPlayer::WaitForStream()
1085 {
1086   // should we wait for our other stream as well?
1087   // currently we don't.
1088   if (!m_pAudioDecoder[m_currentStream])
1089   {
1090     m_pAudioDecoder[m_currentStream]->WaitCompletion();
1091   }
1092 }