winamp/Src/Plugins/Input/in_wmvdrm/SeekLayer.cpp

377 lines
6.6 KiB
C++

#include "SeekLayer.h"
#include "Main.h"
#include "output/AudioOut.h"
#include "util.h"
#include <assert.h>
using namespace Nullsoft::Utility;
struct OpenThreadData
{
IWMReaderCallback *callback;
wchar_t *url;
IWMReader *reader;
void open()
{
reader->Open(url, callback, 0);
}
OpenThreadData(IWMReader *_reader, const wchar_t *_url, IWMReaderCallback *_callback)
{
reader = _reader;
reader->AddRef();
callback = _callback;
callback->AddRef();
url = _wcsdup(_url);
}
~OpenThreadData()
{
free(url);
reader->Release();
callback->Release();
}
};
DWORD WINAPI OpenThread(void *param)
{
OpenThreadData *data = (OpenThreadData *)param;
data->open();
delete data;
return 0;
}
#define NEW_SEEK
SeekLayer::SeekLayer(IWMReader *_reader, ClockLayer *_clock)
: seekPos(0), reader(_reader), playState(PLAYSTATE_CLOSED), metadata(NULL), clock(_clock),
needPause(false), paused(false), needStop(false),
seekGuard(GUARDNAME("Seek Guard")),
oldState_buffer(PLAYSTATE_NONE)
{
reader->AddRef();
reader->QueryInterface(&reader2);
}
void SeekLayer::DoStop()
{
if (paused)
reader->Resume();
reader->Stop();
First().Stopping();
First().Kill();
if (paused)
{
paused = false;
out->Pause(0);
}
needStop = false;
}
void SeekLayer::SeekTo(long position)
{
AutoLock lock (seekGuard LOCKNAME("SeekTo"));
if (paused)
{
reader->Resume();
}
First().Stopping();
First().Kill();
seekPos = position;
clock->SetLastOutputTime(position);
clock->SetStartTimeMilliseconds(position);
out->Flush(position);
QWORD qSeekPos = position;
qSeekPos *= 10000;
reader->Start(qSeekPos, 0, 1.0f, NULL);
if (paused)
{
reader->Pause();
}
}
void SeekLayer::Pause()
{
AutoLock lock (seekGuard LOCKNAME("Pause"));
if (playState == PLAYSTATE_STARTED)
{
paused = true;
reader->Pause();
out->Pause(1);
}
else
{
needPause = true;
}
}
int SeekLayer::Open(const wchar_t *filename, IWMReaderCallback *callback)
{
AutoLock lock (seekGuard LOCKNAME("Open"));
assert(playState == PLAYSTATE_CLOSED);
needStop = false;
playState = PLAYSTATE_OPENING;
DWORD dummyId;
CreateThread(NULL, 0, OpenThread, new OpenThreadData(reader, filename, callback), 0, &dummyId);
return 0;
}
void SeekLayer::Stop()
{
AutoLock lock (seekGuard LOCKNAME("Stop"));
needStop = true;
switch (playState)
{
case PLAYSTATE_BUFFERING:
// needStop=false;
reader2->StopBuffering();
// reader->Stop();
break;
case PLAYSTATE_OPENING:
// wait for it to open (or connect) and then we'll kill it there
break;
case PLAYSTATE_NONE:
case PLAYSTATE_STOPPED:
if (FAILED(reader->Close())) // reader->Close() is sometimes synchronous, and sometimes not valid here
{
playState = PLAYSTATE_CLOSED;
return ;
}
break;
case PLAYSTATE_OPENED:
case PLAYSTATE_STARTED:
reader->Stop();
First().Stopping();
First().Kill();
break;
case PLAYSTATE_CLOSED:
needStop = false;
break;
/*
case PLAYSTATE_BUFFERING:
reader2->StopBuffering();
reader->Stop();
break;*/
case PLAYSTATE_SEEK:
break;
}
while (playState != PLAYSTATE_CLOSED)
{
lock.ManualUnlock();
Sleep(55);
lock.ManualLock(MANUALLOCKNAME("[Manual Lock]Stop"));
}
needStop = false;
}
void SeekLayer::Unpause()
{
AutoLock lock (seekGuard LOCKNAME("Unpause"));
if (playState == PLAYSTATE_STARTED)
{
paused = false;
out->Pause(0);
reader->Resume();
clock->Clock();
}
else
{
needPause = false;
}
}
void SeekLayer::Opened()
{
{
AutoLock lock (seekGuard LOCKNAME("SeekLayer::Opened"));
if (needStop)
{
playState = PLAYSTATE_OPENED;
lock.ManualUnlock();
reader->Close();
lock.ManualLock(MANUALLOCKNAME("[Manual Lock]SeekLayer::Opened"));
return ;
}
playState = PLAYSTATE_OPENED;
}
WMHandler::Opened();
}
void SeekLayer::Stopped()
{
{
AutoLock lock (seekGuard LOCKNAME("Stopped"));
if (needStop)
{
playState = PLAYSTATE_STOPPED;
lock.ManualUnlock();
reader->Close();
lock.ManualLock(MANUALLOCKNAME("Stopped"));
}
else
{
playState = PLAYSTATE_STOPPED;
}
WMHandler::Stopped();
}
}
void SeekLayer::Started()
{
{
AutoLock lock (seekGuard LOCKNAME("Started"));
playState = PLAYSTATE_STARTED;
if (needStop)
{
reader->Stop();
First().Stopping();
First().Kill();
return ;
}
else if (needPause)
{
Pause();
needPause = false;
}
}
WMHandler::Started();
}
void SeekLayer::Closed()
{
playState = PLAYSTATE_CLOSED;
paused = false;
needPause = false;
needStop = false;
seekPos = 0;
WMHandler::Closed();
}
void SeekLayer::BufferingStarted()
{
{
AutoLock lock (seekGuard LOCKNAME("BufferingStarted"));
if (playState == PLAYSTATE_OPENED)
oldState_buffer = PLAYSTATE_NONE;
else
oldState_buffer = playState;
if (playState != PLAYSTATE_STARTED)
playState = PLAYSTATE_BUFFERING;
if (needStop)
reader2->StopBuffering();
}
WMHandler::BufferingStarted();
}
void SeekLayer::BufferingStopped()
{
{
AutoLock lock (seekGuard LOCKNAME("BufferingStopped"));
if (needStop)
reader->Stop();
playState = oldState_buffer;
}
WMHandler::BufferingStopped();
}
void SeekLayer::EndOfFile()
{
{
AutoLock lock (seekGuard LOCKNAME("EndOfFile"));
if (needStop)
return ;
}
WMHandler::EndOfFile();
}
void SeekLayer::Connecting()
{
{
AutoLock lock (seekGuard LOCKNAME("SeekLayer::Connecting"));
if (needStop)
{
playState = PLAYSTATE_NONE;
lock.ManualUnlock();
reader->Close();
lock.ManualLock(MANUALLOCKNAME("[Manual Lock]SeekLayer::Connecting"));
return ;
}
playState = PLAYSTATE_NONE;
}
WMHandler::Connecting();
}
void SeekLayer::Locating()
{
{
AutoLock lock (seekGuard LOCKNAME("SeekLayer::Locating"));
if (needStop)
{
playState = PLAYSTATE_NONE;
lock.ManualUnlock();
reader->Close();
lock.ManualLock(MANUALLOCKNAME("[Manual Lock]SeekLayer::Locating"));
return ;
}
playState = PLAYSTATE_NONE;
}
WMHandler::Locating();
}
void SeekLayer::OpenCalled()
{
{
AutoLock lock (seekGuard LOCKNAME("SeekLayer::OpenCalled"));
if (needStop)
{
playState = PLAYSTATE_NONE;
lock.ManualUnlock();
reader->Close();
lock.ManualLock(MANUALLOCKNAME("[Manual Lock]SeekLayer::OpenCalled"));
return ;
}
playState = PLAYSTATE_NONE;
}
WMHandler::OpenCalled();
}
void SeekLayer::OpenFailed()
{
{
AutoLock lock (seekGuard LOCKNAME("SeekLayer::OpenFailed"));
if (playState == PLAYSTATE_OPENING)
playState = PLAYSTATE_NONE;
}
WMHandler::OpenFailed();
}
void SeekLayer::Error()
{
{
AutoLock lock (seekGuard LOCKNAME("SeekLayer::Error"));
/*if (playState == PLAYSTATE_OPENING)
playState = PLAYSTATE_CLOSED;
else */if (playState != PLAYSTATE_CLOSED)
playState = PLAYSTATE_NONE;
}
WMHandler::Error();
}