📄 receiver.cpp
字号:
#include <windows.h>
#include "maplay.h"
#include "receiver.h"
#include <stdio.h>
CReceiver::CReceiver() :
m_eventStart(FALSE), m_eventBuf(TRUE), m_eventBufFree(TRUE)
{
m_hwndMessage = NULL;
m_fInitialized = FALSE;
m_hThread = NULL;
m_dwThread = 0;
m_szURL[0] = NULL;
m_szProxy[0] = NULL;
m_szURL[0] = NULL;
m_szProxy[0] = NULL;
m_szIcyName[0] = NULL;
m_szIcyGenre[0] = NULL;
m_szIcyURL[0] = NULL;
m_fUseProxy = FALSE;
_tcscpy(m_szUserAgent, DEF_USER_AGENT);
m_hSock = INVALID_SOCKET;
m_cbMetaData = 0;
m_cbMetaDataInterval = 0;
m_cbMetaDataBuf = 0;
m_fShoutcast = FALSE;
m_fStop = FALSE;
m_fEos = FALSE;
m_cBuf = 32;
m_cPreBuf = 16;
// Winsock偺弶婜壔
WSADATA WsaData;
if (!WSAStartup(MAKEWORD(1, 1), &WsaData))
m_fInitialized = TRUE;
}
CReceiver::~CReceiver()
{
Close();
if (m_fInitialized) {
WSACleanup();
}
}
BOOL CReceiver::Open(LPCTSTR pszURL)
{
if (_tcsncmp(pszURL, _T("http://"), 7) != 0)
return FALSE;
if (!m_fInitialized)
return FALSE;
_tcscpy(m_szURL, pszURL);
return TRUE;
}
BOOL CReceiver::Connect()
{
if (!m_fInitialized)
return FALSE;
CAutoLock lock(&m_csecConnect);
Disconnect();
// 僶僢僼傽傪嶌惉
if (!PrepareBuffer())
return FALSE;
m_fShoutcast = FALSE;
m_fStop = FALSE;
m_fEos = FALSE;
// 庴怣梡僗儗僢僪傪嶌惉
m_eventStart.Reset();
m_hThread = CreateThread(NULL, 0, ReceiverThreadProc, this, 0, &m_dwThread);
if (!m_hThread)
return FALSE;
// 奐巒張棟偑姰椆偡傞傑偱懸婡
HANDLE handles[] = {m_eventStart, m_hThread};
int nRet = WaitForMultipleObjects(sizeof(handles)/ sizeof(HANDLE), handles, FALSE, INFINITE);
if (nRet != WAIT_OBJECT_0) {
UnprepareBuffer();
return FALSE;
}
return TRUE;
}
void CReceiver::Disconnect()
{
CAutoLock lock(&m_csecConnect);
// 僗儗僢僪偑廔椆偡傞傑偱懸偮
if (m_hThread) {
m_fStop = TRUE;
m_eventBufFree.Set();
m_eventBuf.Set();
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
m_hThread = NULL;
}
// 僶僢僼傽傪攋婞
UnprepareBuffer();
m_fShoutcast = FALSE;
m_fStop = FALSE;
m_fEos = FALSE;
m_cbMetaDataBuf = 0;
}
void CReceiver::Close()
{
Disconnect();
m_szURL[0] = NULL;
m_szIcyName[0] = NULL;
m_szIcyGenre[0] = NULL;
m_szIcyURL[0] = NULL;
m_cbMetaDataBuf = 0;
}
BOOL CReceiver::Read(LPBYTE pbBuffer, DWORD cbBuffer, LPDWORD pcbRead)
{
*pcbRead = 0;
while (*pcbRead < cbBuffer) {
// 僶僢僼傽傪懸偮
while (!m_eventBuf.Lock(100)) {
// Socket偑暵偠傜傟偰偄偰丄僶僢僼傽偑側偄応崌偼傕偆庴怣偱偒傞僨乕僞偼側偄
if (m_hSock == INVALID_SOCKET)
return FALSE;
}
if (m_listBuf.GetCount() == 0)
return FALSE;
// 僐僺乕
CAutoLock lock(&m_csecBuf);
RECV_BUF* pBuf = (RECV_BUF*)m_listBuf.GetAt(0);
DWORD cb = min(pBuf->cbRecv - pBuf->cbUsed, cbBuffer - *pcbRead);
memcpy(pbBuffer + *pcbRead, pBuf->pbBuf + pBuf->cbUsed, cb);
*pcbRead += cb;
pBuf->cbUsed += cb;
if (pBuf->cbUsed == pBuf->cbRecv) {
m_listBuf.RemoveAt(0);
m_listBufFree.Add((DWORD)pBuf);
m_eventBufFree.Set();
}
if (m_listBuf.GetCount() == 0)
m_eventBuf.Reset();
}
return TRUE;
}
void CReceiver::SetProxy(BOOL fUseProxy, LPCTSTR pszProxy)
{
m_fUseProxy = fUseProxy;
_tcscpy(m_szProxy, pszProxy);
}
BOOL CReceiver::GetProxy(LPTSTR pszProxy)
{
_tcscpy(pszProxy, m_szProxy);
return m_fUseProxy;
}
void CReceiver::SetUserAgent(LPCTSTR pszAgent)
{
_tcscpy(m_szUserAgent, pszAgent);
}
void CReceiver::GetUserAgent(LPTSTR pszAgent)
{
_tcscpy(pszAgent, m_szUserAgent);
}
BOOL CReceiver::SetBufferCount(int nCount)
{
//丂僶僢僼傽偑婛偵嶌傜傟偰偄傞応崌偼晄壜
if (m_listBuf.GetCount() || m_listBufFree.GetCount())
return FALSE;
// 1埲壓偼僟儊
if (nCount < 2)
return FALSE;
m_cBuf = nCount;
if (m_cPreBuf > m_cBuf)
m_cPreBuf = m_cBuf;
return TRUE;
}
int CReceiver::GetBufferCount()
{
return m_cBuf;
}
BOOL CReceiver::SetPrebufferingCount(int nCount)
{
if (nCount > m_cBuf)
return FALSE;
// 1埲壓偼僟儊
if (nCount < 2)
return FALSE;
m_cPreBuf = nCount;
return TRUE;
}
int CReceiver::GetPrebufferingCount()
{
return m_cPreBuf;
}
int CReceiver::GetBufferingCount()
{
return m_listBuf.GetCount();
}
void CReceiver::GetBufferInfo(DWORD* pcbTotal, DWORD* pcbBuffered)
{
if (m_hSock == INVALID_SOCKET) {
*pcbTotal = *pcbBuffered = 0;
return;
}
*pcbTotal = m_cBuf * RECV_BUFF_SIZE;
*pcbBuffered = m_listBuf.GetCount() * RECV_BUFF_SIZE;
}
BOOL CReceiver::GetStreamInfo(LPTSTR pszName, LPTSTR pszGenre, LPTSTR pszURL)
{
if (!_tcslen(m_szIcyName) && !_tcslen(m_szIcyGenre) && !_tcslen(m_szIcyURL))
return FALSE;
BOOL fRet = FALSE;
if (pszName) {
*pszName = NULL;
if (_tcslen(m_szIcyName)) {
_tcscpy(pszName, m_szIcyName);
fRet = TRUE;
}
}
if (pszGenre) {
*pszGenre = NULL;
if (_tcslen(m_szIcyGenre)) {
_tcscpy(pszGenre, m_szIcyGenre);
fRet = TRUE;
}
}
if (pszURL) {
*pszURL = NULL;
if (_tcslen(m_szIcyURL)) {
_tcscpy(pszURL, m_szIcyURL);
fRet = TRUE;
}
}
return fRet;
}
BOOL CReceiver::GetStreamTitle(LPTSTR pszTitle)
{
*pszTitle = NULL;
char szTitle[MAX_URL] = {0};
if (m_cbMetaDataBuf && m_cbMetaDataBuf == m_bMetaDataBuf[0] * 16 + 1) {
char* psz = strstr((char*)m_bMetaDataBuf, "StreamTitle=");
if (psz) {
psz += strlen("StreamTitle='");
char* psz2 = strchr(psz, ';');
if (psz2) {
if (*(psz2 - 1) == '\'')
psz2--;
strncpy(szTitle, psz, psz2 - psz);
#ifdef _UNICODE
MultiByteToWideChar(CP_ACP, 0, szTitle, -1, pszTitle, MAX_URL);
#else
strcpy(pszTitle, szTitle);
#endif
return TRUE;
}
}
}
return FALSE;
}
// protected
DWORD WINAPI CReceiver::ReceiverThreadProc(LPVOID pParam)
{
return ((CReceiver*)pParam)->ReceiverThread();
}
DWORD CReceiver::ReceiverThread()
{
{
TCHAR szURL[MAX_URL];
TCHAR szRedirect[MAX_URL];
_tcscpy(szURL, m_szURL);
while (!ConnectServer(szURL, szRedirect)) {
if (!_tcslen(szRedirect))
return 0;
_tcscpy(szURL, szRedirect);
}
}
fd_set fdRecv;
int nRecv, nTimeout;
RECV_BUF* pBuf = NULL;
RECV_BUF Buf;
struct timeval tv = {0, RECV_INTERVAL};
pBuf = (RECV_BUF*)m_listBufFree.RemoveAt(0);
if (m_listBufFree.GetCount() == 0)
m_eventBufFree.Reset();
m_eventStart.Set();
while (TRUE) {
// 僶僢僼傽傪庢摼偡傞
if (!pBuf) {
m_eventBufFree.Lock();
if (m_fStop)
goto done;
CAutoLock lock(&m_csecBuf);
pBuf = (RECV_BUF*)m_listBufFree.RemoveAt(0);
pBuf->cbRecv = 0;
pBuf->cbUsed = 0;
if (m_listBufFree.GetCount() == 0)
m_eventBufFree.Reset();
}
while (pBuf->cbRecv < RECV_BUFF_SIZE) {
nTimeout = 0;
while (TRUE) {
if (m_fStop)
goto done;
// 僞僀儉傾僂僩偡傞傑偱懸偮
FD_ZERO(&fdRecv);
FD_SET(m_hSock, &fdRecv);
if (select(NULL, &fdRecv, 0, 0, &tv) != SOCKET_ERROR && FD_ISSET(m_hSock, &fdRecv))
break;
nTimeout += RECV_INTERVAL;
if (nTimeout > RECV_RECEIVE_TIMEOUT)
goto done;
}
// 庴怣偡傞
nRecv = recv(m_hSock, (char*)pBuf->pbBuf + pBuf->cbRecv,
RECV_BUFF_SIZE - pBuf->cbRecv, 0);
if (nRecv == 0) {
m_fEos = TRUE;
break;
}
if (nRecv == SOCKET_ERROR)
goto done;
// MetaData偺僠僃僢僋傪峴偆
nRecv -= CheckMetaData(pBuf->pbBuf + pBuf->cbRecv, nRecv);
pBuf->cbRecv += nRecv;
}
if (m_fStop)
goto done;
// 弌椡張棟
if (pBuf && pBuf->cbRecv) {
CAutoLock lock(&m_csecBuf);
m_listBuf.Add((DWORD)pBuf);
pBuf = NULL;
m_eventBuf.Set();
}
if (m_fEos)
goto done;
}
done:
DisconnectServer();
return 0;
}
BOOL CReceiver::ConnectServer(LPCTSTR pszURL, LPTSTR pszRedirect)
{
int nPort, nLen = 0, nRet = 0, nTimeout = 0;
unsigned long addr, val = 1;
struct sockaddr_in sAddr;
struct hostent* pHost;
char* psz;
char szURL[MAX_URL];
char szProxy[MAX_URL];
char szHostName[MAX_URL] = {0};
char szUserAgent[MAX_URL];
char szRequest[MAX_URL * 4];
char szRecv[RECV_BUFF_SIZE];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -