rtoss - Blame information for rev 26

Subversion Repositories:
Rev:
Rev Author Line No. Line
14 roytam 1 #include <windows.h>
2 #include "maplay.h"
3 #include "receiver.h"
4 #include <stdio.h>
5  
6 CReceiver::CReceiver() :
7 m_eventStart(FALSE), m_eventBuf(TRUE), m_eventBufFree(TRUE)
8 {
9         m_hwndMessage = NULL;
10         m_fInitialized = FALSE;
11         m_hThread = NULL;
12         m_dwThread = 0;
13  
14         m_szURL[0] = NULL;
15         m_szProxy[0] = NULL;
16         m_szURL[0] = NULL;
17         m_szProxy[0] = NULL;
18         m_szIcyName[0] = NULL;
19         m_szIcyGenre[0] = NULL;
20         m_szIcyURL[0] = NULL;
21         m_fUseProxy = FALSE;
22  
23         _tcscpy(m_szUserAgent, DEF_USER_AGENT);
24         m_hSock = INVALID_SOCKET;
25         m_cbMetaData = 0;
26         m_cbMetaDataInterval = 0;
27         m_cbMetaDataBuf = 0;
28  
29         m_fShoutcast = FALSE;
30         m_fStop = FALSE;
31         m_fEos = FALSE;
26 roytam 32         m_cBuf = 64;
33         m_cPreBuf = 32;
14 roytam 34  
35         // Winsockの初期化
36         WSADATA WsaData;
37         if (!WSAStartup(MAKEWORD(1, 1), &WsaData))
38                 m_fInitialized = TRUE;
39 }
40  
41 CReceiver::~CReceiver()
42 {
43         Close();
44         if (m_fInitialized) {
45                 WSACleanup();
46         }
47 }
48  
49 BOOL CReceiver::Open(LPCTSTR pszURL)
50 {
51         if (_tcsncmp(pszURL, _T("http://"), 7) != 0)
52                 return FALSE;
53  
54         if (!m_fInitialized)
55                 return FALSE;
56  
57         _tcscpy(m_szURL, pszURL);
58         return TRUE;
59 }
60  
61 BOOL CReceiver::Connect()
62 {
63         if (!m_fInitialized)
64                 return FALSE;
65  
66         CAutoLock lock(&m_csecConnect);
67         Disconnect();
68  
69         // バッファを作成
70         if (!PrepareBuffer())
71                 return FALSE;
72  
73         m_fShoutcast = FALSE;
74         m_fStop = FALSE;
75         m_fEos = FALSE;
76  
77         // 受信用スレッドを作成
78         m_eventStart.Reset();
79         m_hThread = CreateThread(NULL, 0, ReceiverThreadProc, this, 0, &m_dwThread);
80         if (!m_hThread)
81                 return FALSE;
82  
83         // 開始処理が完了するまで待機
84         HANDLE handles[] = {m_eventStart, m_hThread};
85         int nRet = WaitForMultipleObjects(sizeof(handles)/ sizeof(HANDLE), handles, FALSE, INFINITE);
86         if (nRet != WAIT_OBJECT_0) {
87                 UnprepareBuffer();
88                 return FALSE;
89         }
90         return TRUE;
91 }
92  
93 void CReceiver::Disconnect()
94 {
95         CAutoLock lock(&m_csecConnect);
96         // スレッドが終了するまで待つ
97         if (m_hThread) {
98                 m_fStop = TRUE;
99                 m_eventBufFree.Set();
100                 m_eventBuf.Set();
101                 WaitForSingleObject(m_hThread, INFINITE);
102                 CloseHandle(m_hThread);
103                 m_hThread = NULL;
104         }
105         // バッファを破棄
106         UnprepareBuffer();
107         m_fShoutcast = FALSE;
108         m_fStop = FALSE;
109         m_fEos = FALSE;
110  
111         m_cbMetaDataBuf = 0;
112 }
113  
114 void CReceiver::Close()
115 {
116         Disconnect();
117  
118         m_szURL[0] = NULL;
119         m_szIcyName[0] = NULL;
120         m_szIcyGenre[0] = NULL;
121         m_szIcyURL[0] = NULL;
122         m_cbMetaDataBuf = 0;
123 }
124  
125 BOOL CReceiver::Read(LPBYTE pbBuffer, DWORD cbBuffer, LPDWORD pcbRead)
126 {
127         *pcbRead = 0;
128         while (*pcbRead < cbBuffer) {
129                 // バッファを待つ
130                 while (!m_eventBuf.Lock(100)) {
131                         // Socketが閉じられていて、バッファがない場合はもう受信できるデ[タはない
132                         if (m_hSock == INVALID_SOCKET)
133                                 return FALSE;
134                 }
135  
136                 if (m_listBuf.GetCount() == 0)
137                         return FALSE;
138  
139                 // コピ[
140                 CAutoLock lock(&m_csecBuf);
141                 RECV_BUF* pBuf = (RECV_BUF*)m_listBuf.GetAt(0);
142                 DWORD cb = min(pBuf->cbRecv - pBuf->cbUsed, cbBuffer - *pcbRead);
143                 memcpy(pbBuffer + *pcbRead, pBuf->pbBuf + pBuf->cbUsed, cb);
144                 *pcbRead += cb;
145                 pBuf->cbUsed += cb;
146                 if (pBuf->cbUsed == pBuf->cbRecv) {
147                         m_listBuf.RemoveAt(0);
148                         m_listBufFree.Add((DWORD)pBuf);
149                         m_eventBufFree.Set();
150                 }
151  
152                 if (m_listBuf.GetCount() == 0)
153                         m_eventBuf.Reset();
154         }
155  
156         return TRUE;
157 }
158  
159 void CReceiver::SetProxy(BOOL fUseProxy, LPCTSTR pszProxy)
160 {
161         m_fUseProxy = fUseProxy;
162         _tcscpy(m_szProxy, pszProxy);
163 }
164  
165 BOOL CReceiver::GetProxy(LPTSTR pszProxy)
166 {
167         _tcscpy(pszProxy, m_szProxy);
168         return m_fUseProxy;
169 }
170  
171 void CReceiver::SetUserAgent(LPCTSTR pszAgent)
172 {
173         _tcscpy(m_szUserAgent, pszAgent);
174 }
175  
176 void CReceiver::GetUserAgent(LPTSTR pszAgent)
177 {
178         _tcscpy(pszAgent, m_szUserAgent);
179 }
180  
181 BOOL CReceiver::SetBufferCount(int nCount)
182 {
183         // バッファが既に作られている場合は不可
184         if (m_listBuf.GetCount() || m_listBufFree.GetCount())
185                 return FALSE;
186  
187         // 1以下はダメ
188         if (nCount < 2)
189                 return FALSE;
190  
191         m_cBuf = nCount;
192         if (m_cPreBuf > m_cBuf)
193                 m_cPreBuf = m_cBuf;
194         return TRUE;
195 }
196  
197 int CReceiver::GetBufferCount()
198 {
199         return m_cBuf;
200 }
201  
202 BOOL CReceiver::SetPrebufferingCount(int nCount)
203 {
204         if (nCount > m_cBuf)
205                 return FALSE;
206  
207         // 1以下はダメ
208         if (nCount < 2)
209                 return FALSE;
210  
211         m_cPreBuf = nCount;
212         return TRUE;
213 }
214  
215 int CReceiver::GetPrebufferingCount()
216 {
217         return m_cPreBuf;
218 }
219  
220 int CReceiver::GetBufferingCount()
221 {
222         return m_listBuf.GetCount();
223 }
224  
225 void CReceiver::GetBufferInfo(DWORD* pcbTotal, DWORD* pcbBuffered)
226 {
227         if (m_hSock == INVALID_SOCKET) {
228                 *pcbTotal = *pcbBuffered = 0;
229                 return;
230         }
231  
232         *pcbTotal = m_cBuf * RECV_BUFF_SIZE;
233         *pcbBuffered = m_listBuf.GetCount() * RECV_BUFF_SIZE;
234 }
235  
236 BOOL CReceiver::GetStreamInfo(LPTSTR pszName, LPTSTR pszGenre, LPTSTR pszURL)
237 {
238         if (!_tcslen(m_szIcyName) && !_tcslen(m_szIcyGenre) && !_tcslen(m_szIcyURL))
239                 return FALSE;
240  
241         BOOL fRet = FALSE;
242         if (pszName) {
243                 *pszName = NULL;
244                 if (_tcslen(m_szIcyName)) {
245                         _tcscpy(pszName, m_szIcyName);
246                         fRet = TRUE;
247                 }
248         }
249         if (pszGenre) {
250                 *pszGenre = NULL;
251                 if (_tcslen(m_szIcyGenre)) {
252                         _tcscpy(pszGenre, m_szIcyGenre);
253                         fRet = TRUE;
254                 }
255         }
256         if (pszURL) {
257                 *pszURL = NULL;
258                 if (_tcslen(m_szIcyURL)) {
259                         _tcscpy(pszURL, m_szIcyURL);
260                         fRet = TRUE;
261                 }
262         }
263         return fRet;
264 }
265  
266 BOOL CReceiver::GetStreamTitle(LPTSTR pszTitle)
267 {
268         *pszTitle = NULL;
269  
270         char szTitle[MAX_URL] = {0};
271         if (m_cbMetaDataBuf && m_cbMetaDataBuf == m_bMetaDataBuf[0] * 16 + 1) {
272                 char* psz = strstr((char*)m_bMetaDataBuf, "StreamTitle=");
273                 if (psz) {
274                         psz += strlen("StreamTitle='");
275                         char* psz2 = strchr(psz, ';');
276                         if (psz2) {
277                                 if (*(psz2 - 1) == '\'')
278                                         psz2--;
279  
280                                 strncpy(szTitle, psz, psz2 - psz);
281 #ifdef _UNICODE
282                                 MultiByteToWideChar(CP_ACP, 0, szTitle, -1, pszTitle, MAX_URL);
283 #else
284                                 strcpy(pszTitle, szTitle);
285 #endif
286                                 return TRUE;
287                         }
288                 }
289         }
290         return FALSE;
291 }
292  
293 // protected
294 DWORD WINAPI CReceiver::ReceiverThreadProc(LPVOID pParam)
295 {
296         return ((CReceiver*)pParam)->ReceiverThread();
297 }
298  
299 DWORD CReceiver::ReceiverThread()
300 {
301         {
302                 TCHAR szURL[MAX_URL];
303                 TCHAR szRedirect[MAX_URL];
304                 _tcscpy(szURL, m_szURL);
305                 while (!ConnectServer(szURL, szRedirect)) {
306                         if (!_tcslen(szRedirect))
307                                 return 0;
308                         _tcscpy(szURL, szRedirect);
309                 }
310         }
311  
312         fd_set fdRecv;
313         int     nRecv, nTimeout;
314         RECV_BUF* pBuf = NULL;
315         RECV_BUF Buf;
316         struct timeval tv = {0, RECV_INTERVAL};
317         pBuf = (RECV_BUF*)m_listBufFree.RemoveAt(0);
318         if (m_listBufFree.GetCount() == 0)
319                 m_eventBufFree.Reset();
320  
321         m_eventStart.Set();
322         while (TRUE) {
323                 // バッファを取得する
324                 if (!pBuf) {
325                         m_eventBufFree.Lock();
326                         if (m_fStop)
327                                 goto done;
328  
329                         CAutoLock lock(&m_csecBuf);
330                         pBuf = (RECV_BUF*)m_listBufFree.RemoveAt(0);
331                         pBuf->cbRecv = 0;
332                         pBuf->cbUsed = 0;
333  
334                         if (m_listBufFree.GetCount() == 0)
335                                 m_eventBufFree.Reset();
336                 }
337                 while (pBuf->cbRecv < RECV_BUFF_SIZE) {
338                         nTimeout = 0;
339                         while (TRUE) {
340                                 if (m_fStop)
341                                         goto done;
342                                 // タイムアウトするまで待つ
343                                 FD_ZERO(&fdRecv);
344                                 FD_SET(m_hSock, &fdRecv);
345                                 if (select(NULL, &fdRecv, 0, 0, &tv) != SOCKET_ERROR && FD_ISSET(m_hSock, &fdRecv))
346                                         break;
347  
348                                 nTimeout += RECV_INTERVAL;
349                                 if (nTimeout > RECV_RECEIVE_TIMEOUT)
350                                         goto done;
351                         }
352  
353                         // 受信する
354                         nRecv = recv(m_hSock, (char*)pBuf->pbBuf + pBuf->cbRecv,
355                                                                                 RECV_BUFF_SIZE - pBuf->cbRecv, 0);
356                         if (nRecv == 0) {
357                                 m_fEos = TRUE;
358                                 break;
359                         }
360                         if (nRecv == SOCKET_ERROR)
361                                 goto done;
362  
363                         // MetaDataのチェックを行う
364                         nRecv -= CheckMetaData(pBuf->pbBuf + pBuf->cbRecv, nRecv);
365                         pBuf->cbRecv += nRecv;
366                 }
367                 if (m_fStop)
368                         goto done;
369  
370                 // 出力処理
371                 if (pBuf && pBuf->cbRecv) {
372                         CAutoLock lock(&m_csecBuf);
373                         m_listBuf.Add((DWORD)pBuf);
374                         pBuf = NULL;
375                         m_eventBuf.Set();
376                 }
377                 if (m_fEos)
378                         goto done;
379         }
380 done:
381         DisconnectServer();
382         return 0;
383 }
384  
385 BOOL CReceiver::ConnectServer(LPCTSTR pszURL, LPTSTR pszRedirect)
386 {
387         int nPort, nLen = 0, nRet = 0, nTimeout = 0;
388         unsigned long addr, val = 1;
389         struct sockaddr_in sAddr;
390         struct hostent* pHost;
391         char* psz;
392         char szURL[MAX_URL];
393         char szProxy[MAX_URL];
394         char szHostName[MAX_URL] = {0};
395         char szUserAgent[MAX_URL];
396         char szRequest[MAX_URL * 4];
397         char szRecv[RECV_BUFF_SIZE];
398         fd_set  fdRecv, fdError;
399         struct timeval tv = {0, RECV_INTERVAL};
400         RECV_BUF* pBuf;
401  
402         *pszRedirect = NULL;
403 #ifdef _UNICODE
404         WideCharToMultiByte(CP_ACP, 0, pszURL, -1, szURL, MAX_URL, 0, 0);
405         WideCharToMultiByte(CP_ACP, 0, m_szProxy, -1, szProxy, MAX_URL, 0, 0);
406         WideCharToMultiByte(CP_ACP, 0, m_szUserAgent, -1, szUserAgent, MAX_URL, 0, 0);
407 #else
408         strcpy(szURL, pszURL);
409         strcpy(szProxy, m_szProxy);
410         strcpy(szUserAgent, m_szUserAgent);
411 #endif
412         if (!strlen(szURL))
413                 return FALSE;
414  
415         // URLを解析する
416         // Proxyサ[バ[が設定されているときはサ[バ[アドレスを解析
417         if (m_fUseProxy && strlen(szProxy)) {
418                 if (strncmp(szProxy, "http://", strlen("http://"))) {
419                         if (sscanf(szProxy, "%[^:/]:%d", szHostName, &nPort) < 2)
420                                 nPort = RECV_HTTP;
421                 }
422                 else {
423                         if (sscanf(szProxy, "http://%[^:/]:%d", szHostName, &nPort) < 2)
424                                 nPort = RECV_HTTP;
425                 }
426                 psz = szURL;   
427         }
428         else {
429                 if (strncmp(szURL, "http://", strlen("http://"))) {
430                         if (sscanf(szURL, "%[^:/]:%d", szHostName, &nPort) < 2)
431                                 nPort = RECV_HTTP;
432                         psz = strchr(szURL, '/');
433                 }
434                 else {
435                         if (sscanf(szURL, "http://%[^:/]:%d", szHostName, &nPort) < 2)
436                                 nPort = RECV_HTTP;
437                         psz = strchr(szURL + 7, '/');
438                 }
439         }
440         if (!strlen(szHostName))
441                 return FALSE;
442  
443         // socketの作成
444         m_hSock = socket(PF_INET, SOCK_STREAM, 0);
445         if (m_hSock == INVALID_SOCKET)
446                 return FALSE;
447  
448         // アドレスの取得
449         addr = inet_addr(szHostName);
450         if (addr == SOCKET_ERROR) {
451                 pHost = gethostbyname(szHostName);
452                 if (!pHost)
453                         return FALSE;
454                 addr = *((unsigned long*)(pHost->h_addr_list)[0]);
455         }
456  
457         // 非同期受信に切り替え
458         if (ioctlsocket(m_hSock, FIONBIO, &val) == SOCKET_ERROR)
459                 goto fail;
460  
461         // 接続
462         memset(&sAddr, 0, sizeof(struct sockaddr_in));
463         sAddr.sin_family = AF_INET;
464         sAddr.sin_port = htons((u_short)nPort);
465         sAddr.sin_addr.s_addr = addr;
466         connect(m_hSock, (const sockaddr*)&sAddr, sizeof(sAddr));
467  
468         // タイムアウトするまで待つ
469         nTimeout = 0;
470         while (TRUE) {
471                 if (m_fStop)
472                         goto fail;
473                 FD_ZERO(&fdRecv);
474                 FD_SET(m_hSock, &fdRecv);
475                 FD_ZERO(&fdError);
476                 FD_SET(m_hSock, &fdError);
477                 if (select(NULL, 0, &fdRecv, &fdError, &tv) != SOCKET_ERROR) {
478                         if (FD_ISSET(m_hSock, &fdError))
479                                 goto fail;
480                         else if (FD_ISSET(m_hSock, &fdRecv))
481                                 break;
482                 }
483  
484                 nTimeout += RECV_INTERVAL;
485                 if (nTimeout > RECV_CONNECT_TIMEOUT)
486                         goto fail;
487         }
488  
489         // Request(HTTP)の送信
490         sprintf(szRequest, "GET %s HTTP/1.0\r\nHost: %s\r\nAccept: */*\r\nIcy-MetaData:1\r\nUser-Agent: %s\r\n\r\n",
491         psz ? psz : "/", szHostName, szUserAgent);
492         //x-audiocast-udpport: %d\r\n まだ未対応
493  
494         if (send(m_hSock, szRequest, strlen(szRequest), 0) == SOCKET_ERROR)
495                 goto fail;
496  
497         // ICY (HTTP)ヘッダをすべて受信する
498         psz = NULL;
499         while (!psz && RECV_BUFF_SIZE - nLen - 1 > 0) {
500                 // タイムアウトするまで待つ
501                 nTimeout = 0;
502                 while (TRUE) {
503                         if (m_fStop)
504                                 goto fail;
505                         FD_ZERO(&fdRecv);
506                         FD_SET(m_hSock, &fdRecv);
507                         if (select(NULL, &fdRecv, 0, 0, &tv) != SOCKET_ERROR && FD_ISSET(m_hSock, &fdRecv))
508                                 break;
509  
510                         nTimeout += RECV_INTERVAL;
511                         if (nTimeout > RECV_RECEIVE_TIMEOUT)
512                                 goto fail;
513                 }
514  
515                 int nRecv = recv(m_hSock, szRecv + nLen, RECV_BUFF_SIZE - nLen, 0);
516                 if (!nRecv || nRecv == SOCKET_ERROR)
517                         goto fail;
518  
519                 nLen += nRecv;
520                 if (nRet == 0) {
521                         // エラ[コ[ドをチェック
522                         if (!sscanf(szRecv, " %*s %d", &nRet))
523                                 goto fail;
524  
525                         if (nRet != ICY_OK && nRet != ICY_REDIRECT)
526                                 goto fail;
527                 }
528  
529                 szRecv[nLen] = NULL;
530                 psz = strstr(szRecv, "\r\n\r\n");
531         }
532  
533         if (!psz)       // ヘッダが終わっていない
534                 goto fail;
535  
536         // ヘッダを解析する
537         if (nRet == ICY_REDIRECT) {
538                 // リダイレクト
539                 DisconnectServer();
540                 psz = strstr(szRecv, "Location: ");
541                 if (sscanf(psz, "Location: %256[^\r\n]", szURL) == 1) {
542 #ifdef _UNICODE
543                         MultiByteToWideChar(CP_ACP, 0, szURL, -1, pszRedirect, MAX_URL);
544 #else
545                         strncpy(pszRedirect, szURL, MAX_URL);
546                         pszRedirect[MAX_URL - 1] = NULL;
547 #endif
548                         return FALSE;
549                 }
550         }
551  
552         // name
553         psz = strstr(szRecv, "icy-name");
554         if (psz) {
555                 m_fShoutcast = TRUE;
556                 psz += strlen("icy-name:");
557                 if (sscanf(psz, "%256[^\r\n]", szURL)) {
558                         LPSTR p = szURL;
559                         while (*p == ' ') p++;
560 #ifdef _UNICODE
561                         MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyName, MAX_URL);
562 #else
563                         strcpy(m_szIcyName, p);
564 #endif
565                 }
566         }
567         psz = strstr(szRecv, "ice-name");
568         if (psz) {
569                 m_fShoutcast = TRUE;
570                 psz += strlen("ice-name:");
571                 if (sscanf(psz, "%256[^\r\n]", szURL)) {
572                         LPSTR p = szURL;
573                         while (*p == ' ') p++;
574 #ifdef _UNICODE
575                         MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyName, MAX_URL);
576 #else
577                         strcpy(m_szIcyName, p);
578 #endif
579                 }
580         }
581  
582         // genre
583         psz = strstr(szRecv, "icy-genre");
584         if (psz) {
585                 m_fShoutcast = TRUE;
586                 psz += strlen("icy-genre:");
587                 if (sscanf(psz, "%256[^\r\n]", szURL)) {
588                         LPSTR p = szURL;
589                         while (*p == ' ') p++;
590 #ifdef _UNICODE
591                         MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyGenre, MAX_URL);
592 #else
593                         strcpy(m_szIcyGenre, p);
594 #endif
595                 }
596         }
597         psz = strstr(szRecv, "ice-genre");
598         if (psz) {
599                 m_fShoutcast = TRUE;
600                 psz += strlen("ice-genre:");
601                 if (sscanf(psz, "%256[^\r\n]", szURL)) {
602                         LPSTR p = szURL;
603                         while (*p == ' ') p++;
604 #ifdef _UNICODE
605                         MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyGenre, MAX_URL);
606 #else
607                         strcpy(m_szIcyGenre, p);
608 #endif
609                 }
610         }
611  
612         // url
613         psz = strstr(szRecv, "icy-url");
614         if (psz) {
615                 m_fShoutcast = TRUE;
616                 psz += strlen("icy-url:");
617                 if (sscanf(psz, "%256[^\r\n]", szURL)) {
618                         LPSTR p = szURL;
619                         while (*p == ' ') p++;
620 #ifdef _UNICODE
621                         MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyURL, MAX_URL);
622 #else
623                         strcpy(m_szIcyURL, p);
624 #endif
625                 }
626         }
627         psz = strstr(szRecv, "ice-url");
628         if (psz) {
629                 m_fShoutcast = TRUE;
630                 psz += strlen("ice-url:");
631                 if (sscanf(psz, "%256[^\r\n]", szURL)) {
632                         LPSTR p = szURL;
633                         while (*p == ' ') p++;
634 #ifdef _UNICODE
635                         MultiByteToWideChar(CP_ACP, 0, p, -1, m_szIcyURL, MAX_URL);
636 #else
637                         strcpy(m_szIcyURL, p);
638 #endif
639                 }
640         }
641  
642         //psz = strstr(szRecv, "icy-pub");
643         //psz = strstr(szRecv, "x-audiocast-udpport:");
644  
645         // MetaData
646         psz = strstr(szRecv, "icy-metaint");
647         if (psz) {
648                 psz += strlen("icy-metaint:");
649                 m_cbMetaData = atoi(psz);
650         }
651         else {
652                 m_cbMetaData = 0;
653         }
654         m_cbMetaDataInterval = m_cbMetaData;
655  
656         // ヘッダ以外の受信済みバッファをコピ[する
657         pBuf = (RECV_BUF*)m_listBufFree.GetAt(0);
658         psz = strstr(szRecv, "\r\n\r\n") + 4;
659         pBuf->cbRecv = nLen - (psz - szRecv);
660         memcpy(pBuf->pbBuf, psz, pBuf->cbRecv);
661  
662         // MetaDataのチェック
663         pBuf->cbRecv -= CheckMetaData(pBuf->pbBuf, pBuf->cbRecv);
664  
665         return TRUE;
666 fail:
667         DisconnectServer();
668         return FALSE;
669 }
670  
671 void CReceiver::DisconnectServer()
672 {
673         if (m_hSock != INVALID_SOCKET) {
674                 shutdown(m_hSock, -2);
675                 closesocket(m_hSock);
676                 m_hSock = INVALID_SOCKET;
677         }
678 }
679  
680 BOOL CReceiver::PrepareBuffer()
681 {
682         CAutoLock lock(&m_csecBuf);
683         for (int i = 0; i < (int)m_cBuf; i++) {
684                 RECV_BUF* p = new RECV_BUF;
685                 if (!p) goto fail;
686                 m_listBufFree.Add((DWORD)p);
687         }
688         m_eventBufFree.Set();
689         m_eventBuf.Reset();
690         return TRUE;
691  
692 fail:
693         UnprepareBuffer();
694         return FALSE;
695 }
696  
697 void CReceiver::UnprepareBuffer()
698 {
699         CAutoLock lock(&m_csecBuf);
700         int i;
701         for (i = 0; i < m_listBufFree.GetCount(); i++) {
702                 RECV_BUF* p = (RECV_BUF*)m_listBufFree.GetAt(i);
703                 delete p;
704         }
705         m_listBufFree.RemoveAll();
706         for (i = 0; i < m_listBuf.GetCount(); i++) {
707                 RECV_BUF* p = (RECV_BUF*)m_listBuf.GetAt(i);
708                 delete p;
709         }
710         m_listBuf.RemoveAll();
711  
712         m_eventBufFree.Set();
713         m_eventBuf.Set();
714 }
715  
716 int CReceiver::CheckMetaData(LPBYTE pbBuf, int cbBuf)
717 {
718         if (!m_cbMetaData)
719                 return 0;
720  
721         static TCHAR sz[MAX_URL];
722         if (m_cbMetaDataInterval < 0) {
723                 // 途中まではMetaData
724                 if (cbBuf + m_cbMetaDataInterval <= 0) {
725                         memcpy(m_bMetaDataBuf + m_cbMetaDataBuf, pbBuf, cbBuf);
726                         m_cbMetaDataBuf += cbBuf;
727                         m_cbMetaDataInterval += cbBuf; // また途中までしかない...
728                         return cbBuf;
729                 }
730                 int cbMetaData = -m_cbMetaDataInterval;
731                 memcpy(m_bMetaDataBuf + m_cbMetaDataBuf, pbBuf, cbMetaData);
732                 m_cbMetaDataBuf += cbMetaData;
733                 memmove(pbBuf, pbBuf - m_cbMetaDataInterval, cbBuf - cbMetaData);
734                 m_cbMetaDataInterval = m_cbMetaData - (cbBuf - cbMetaData);
735  
736                 if (m_cbMetaDataInterval < 0) { // 2005/01/16
737                         m_cbMetaDataInterval = m_cbMetaData;
738                         return CheckMetaData(pbBuf, cbBuf - cbMetaData) + cbMetaData;
739                 }
740  
741                 // タイトルの通知を行う
742                 if (GetStreamTitle(sz)) {
743                         NotifyMessage(MAP_MSG_STREAM_TITLE, (WPARAM)sz, 0);
744                 }
745                 return cbMetaData;
746         }
747  
748         if (m_cbMetaDataInterval - cbBuf < 0) {
749                 LPBYTE pMetaData = pbBuf + m_cbMetaDataInterval;
750                 int nSize = *pMetaData * 16 + 1;
751                 if (m_cbMetaDataInterval + nSize > cbBuf) {
752                         // 途中までしかない...
753                         if (*pMetaData) {
754                                 m_cbMetaDataBuf = cbBuf - m_cbMetaDataInterval;
755                                 memcpy(m_bMetaDataBuf, pMetaData, m_cbMetaDataBuf);
756                         }
757                         m_cbMetaDataInterval = cbBuf - m_cbMetaDataInterval - nSize; // マイナス値になる
758                         return nSize + m_cbMetaDataInterval;
759                 }
760  
761                 // MetaDataの内容を取り出す
762                 if (*pMetaData) {
763                         m_cbMetaDataBuf = nSize;
764                         memcpy(m_bMetaDataBuf, pMetaData, m_cbMetaDataBuf);
765                 }
766  
767                 // バッファを詰める
768                 cbBuf = cbBuf - m_cbMetaDataInterval - nSize;
769                 memmove(pMetaData, pMetaData + nSize, cbBuf);
770                 m_cbMetaDataInterval = m_cbMetaData - cbBuf;
771  
772                 if (m_cbMetaDataInterval < 0) { // 2005/01/16
773                         m_cbMetaDataInterval = m_cbMetaData;
774                         return CheckMetaData(pMetaData, cbBuf) + nSize;
775                 }
776  
777                 // タイトルの通知を行う
778                 if (nSize > 1 && GetStreamTitle(sz)) {
779                         NotifyMessage(MAP_MSG_STREAM_TITLE, (WPARAM)sz, 0);
780                 }
781                 return nSize;
782         }
783  
784         m_cbMetaDataInterval -= cbBuf;
785         return 0;
786 }
787  
788 void CReceiver::NotifyMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
789 {
790         if (m_hwndMessage) {
791                 PostMessage(m_hwndMessage, uMsg, wParam, lParam);
792         }
26 roytam 793 }
794  
795 void CReceiver::SetStreamName(LPTSTR pszName)
796 {
797         if (_tcslen(m_szIcyName) == 0) {
798                 _tcscpy(m_szIcyName, pszName);
799         }
14 roytam 800 }