BOOL CP_BuildDirectory(CP_COMPOSITEFILE hComposite) { CPs_CompositeContext* pContext = (CPs_CompositeContext*)hComposite; unsigned int iOffset; CP_CHECKOBJECT(pContext); // Initialise structure pContext->m_pFirstSubFile = NULL; // Scan the composite for the file headers (ignore the end directory stuff) iOffset = 0; while (((iOffset + sizeof(CPs_PKFILE_HEADER)) < pContext->m_dwFileSize) && *(DWORD*)(pContext->m_pFileBase + iOffset) != CPC_PKFILE_DIRMAGIC) { CPs_PKFILE_HEADER* pHeader = (CPs_PKFILE_HEADER*)(pContext->m_pFileBase + iOffset); CPs_SubFile* pNewSubFile; if (pHeader->m_dwSig != CPC_PKFILE_MAGIC || (pHeader->m_wBITs & CPC_PKFILE_BITS_ENCRYPTED) || (pHeader->m_wBITs & CPC_PKFILE_BITS_STREAMED) || (pHeader->m_wMethod != CPC_PKFILE_METHOD_STORED && pHeader->m_wMethod != CPC_PKFILE_METHOD_DEFLATED)) { CP_TRACE0("ZIP format not understood"); return FALSE; } // Create subfile object pNewSubFile = (CPs_SubFile*)malloc(sizeof(*pNewSubFile)); pNewSubFile->m_pNext = pContext->m_pFirstSubFile; pContext->m_pFirstSubFile = pNewSubFile; // Init subfile members pNewSubFile->m_pcName = (char*)malloc(pHeader->m_wFilenameLen + 1); memcpy(pNewSubFile->m_pcName, pContext->m_pFileBase + iOffset + sizeof(*pHeader), pHeader->m_wFilenameLen); pNewSubFile->m_pcName[pHeader->m_wFilenameLen] = '\0'; pNewSubFile->m_wMethod = pHeader->m_wMethod; pNewSubFile->m_dwCRC32 = pHeader->m_dwCRC32; pNewSubFile->m_iCompressedSize = pHeader->m_dwCompressedSize; pNewSubFile->m_iUncompressedSize = pHeader->m_dwDecompressedSize; pNewSubFile->m_iFileOffset = iOffset + sizeof(*pHeader) + pHeader->m_wFilenameLen + pHeader->m_wExtraFieldLen; CP_TRACE1("SubFile:\"%s\"", pNewSubFile->m_pcName); // Skip to next file iOffset += sizeof(*pHeader) + pHeader->m_dwCompressedSize + pHeader->m_wFilenameLen + pHeader->m_wExtraFieldLen; } return TRUE; }
void CPlaylistWindow_CreateIPEdit(const int iItem, const int iSubItem) { RECT rSubItem; const char* pcClass; DWORD dwStyle; int iSearchItemIDX; UINT uiControlID; BOOL bClearNonSelectedItems; CP_HPLAYLISTITEM hClickedItem; HWND hWndList; int iNumItemsSelected; // If the clicked item is not read/write then skip this hClickedItem = (CP_HPLAYLISTITEM)CLV_GetItemData(globals.m_hPlaylistViewControl, iItem); if (CPLI_GetReadWriteState(hClickedItem) != rwsReadWrite) { MessageBox(windows.m_hWndPlaylist, "This file's ID3 tag cannot be updated. This is because CoolPlayer cannot write to this file.", "Cannot update tag", MB_OK | MB_ICONSTOP); return; } // For some sub items it is not logical to multi update - action these if (iSubItem == PLAYLIST_TITLE) bClearNonSelectedItems = TRUE; else bClearNonSelectedItems = FALSE; // Go through the selected items and remove the selection of items that // cannot be written to (eg because of a read only file) iSearchItemIDX = CLV_GetNextSelectedItem(globals.m_hPlaylistViewControl, CPC_INVALIDITEM); iNumItemsSelected = 1; for (;iSearchItemIDX != -1; iSearchItemIDX = CLV_GetNextSelectedItem(globals.m_hPlaylistViewControl, iSearchItemIDX)) { CP_HPLAYLISTITEM hItem = (CP_HPLAYLISTITEM)CLV_GetItemData(globals.m_hPlaylistViewControl, iSearchItemIDX); CPLI_ReadTag(hItem); // We've already checked this item if (iSearchItemIDX == iItem) continue; iNumItemsSelected++; if (bClearNonSelectedItems == TRUE || CPLI_GetReadWriteState(hItem) != rwsReadWrite) CLV_SetItemSelected(globals.m_hPlaylistViewControl, iSearchItemIDX, FALSE); } // If the "track number" column was clicked - and there are multiple selections - auto number them if (iSubItem == PLAYLIST_TRACKNUM && iNumItemsSelected > 1) { char cStatusMessage[1024]; int iTrackNumber; // Autonumber SetCursor(LoadCursor(NULL, IDC_WAIT)); iSearchItemIDX = CLV_GetNextSelectedItem(globals.m_hPlaylistViewControl, CPC_INVALIDITEM); iTrackNumber = 1; for (;iSearchItemIDX != CPC_INVALIDITEM; iSearchItemIDX = CLV_GetNextSelectedItem(globals.m_hPlaylistViewControl, iSearchItemIDX)) { CP_HPLAYLISTITEM hItem = (CP_HPLAYLISTITEM)CLV_GetItemData(globals.m_hPlaylistViewControl, iSearchItemIDX); sprintf(cStatusMessage, "Tagging \"%s\"", CPLI_GetFilename(hItem)); CP_TRACE1("status: %s", cStatusMessage); CPIC_SetIndicatorValue("status", cStatusMessage); UpdateWindow(IF_GetHWnd(windows.m_hifPlaylist)); CPLI_SetTrackNum(hItem, iTrackNumber); CPLI_WriteTag(hItem); iTrackNumber++; } SetCursor(LoadCursor(NULL, IDC_ARROW)); CPIC_SetIndicatorValue("status", NULL); return; } // If the length was clicked - work out the lengths for all selected items if (iSubItem == PLAYLIST_LENGTH) { char cStatusMessage[1024]; SetCursor(LoadCursor(NULL, IDC_WAIT)); iSearchItemIDX = CLV_GetNextSelectedItem(globals.m_hPlaylistViewControl, CPC_INVALIDITEM); for (; iSearchItemIDX != CPC_INVALIDITEM; iSearchItemIDX = CLV_GetNextSelectedItem(globals.m_hPlaylistViewControl, iSearchItemIDX)) { CP_HPLAYLISTITEM hItem = (CP_HPLAYLISTITEM)CLV_GetItemData(globals.m_hPlaylistViewControl, iSearchItemIDX); CPLI_CalculateLength(hItem); sprintf(cStatusMessage, "Tagging \"%s\"", CPLI_GetFilename(hItem)); CPIC_SetIndicatorValue("status", cStatusMessage); CP_TRACE1("status: %s", cStatusMessage); UpdateWindow(IF_GetHWnd(windows.m_hifPlaylist)); CPLI_WriteTag(hItem); } SetCursor(LoadCursor(NULL, IDC_ARROW)); CPIC_SetIndicatorValue("status", NULL); return; } // We want to get the subitem's rect in the co-ordinate space of the dialog hWndList = CLV_GetHWND(globals.m_hPlaylistViewControl); CLV_GetItemSubRect(globals.m_hPlaylistViewControl, &rSubItem, iItem, iSubItem); ClientToScreen(hWndList, (POINT*)&rSubItem); ClientToScreen(hWndList, ((POINT*)&rSubItem) + 1); ScreenToClient(IF_GetHWnd(windows.m_hifPlaylist), (POINT*)&rSubItem); ScreenToClient(IF_GetHWnd(windows.m_hifPlaylist), ((POINT*)&rSubItem) + 1); if (iSubItem == PLAYLIST_GENRE) { // int iRectHeight = rSubItem.bottom-rSubItem.top; // int iListHeight = iRectHeight<<3; InflateRect(&rSubItem, 2, 2); pcClass = "COMBOBOX"; uiControlID = IDC_PL_FLOATINGCOMBO; dwStyle = CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL; rSubItem.bottom += (rSubItem.bottom - rSubItem.top) << 3; } else { InflateRect(&rSubItem, 2, 2); pcClass = "EDIT"; dwStyle = ES_AUTOHSCROLL; uiControlID = IDC_PL_FLOATINGEDIT; if (iSubItem == PLAYLIST_TRACKNUM || iSubItem == PLAYLIST_YEAR) dwStyle |= ES_NUMBER; } // Setup window class and style (the Genre window will be a combo) globals.m_bIP_InhibitUpdates = TRUE; windows.wnd_playlist_IPEdit = CreateWindow(pcClass, "", WS_CHILD | WS_BORDER | WS_CLIPSIBLINGS | dwStyle, rSubItem.left, rSubItem.top, rSubItem.right - rSubItem.left, rSubItem.bottom - rSubItem.top, IF_GetHWnd(windows.m_hifPlaylist), (HMENU)uiControlID, GetModuleHandle(NULL), NULL); SetWindowPos(windows.wnd_playlist_IPEdit, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); ShowWindow(windows.wnd_playlist_IPEdit, SW_SHOW); SetFocus(windows.wnd_playlist_IPEdit); // Setup the font in the control SendMessage(windows.wnd_playlist_IPEdit, WM_SETFONT, (WPARAM)glb_pSkin->mpl_hfFont, MAKELPARAM(TRUE, 0)); // Hook the listview window (so that we can dismiss on VScroll) globals.m_hhkListView_Posted = SetWindowsHookEx(WH_GETMESSAGE, exp_ListViewHookProc_Posted, NULL, GetCurrentThreadId()); // Add the genre items to the list if (iSubItem == PLAYLIST_GENRE) { int iGenreIDX; for (iGenreIDX = 0; iGenreIDX < CIC_NUMGENRES; iGenreIDX++) { int iNewItemIDX = SendMessage(windows.wnd_playlist_IPEdit, CB_ADDSTRING, 0L, (LPARAM)glb_pcGenres[iGenreIDX]); SendMessage(windows.wnd_playlist_IPEdit, CB_SETITEMDATA, (WPARAM)iNewItemIDX, (LPARAM)iGenreIDX); } } // Setup the initial string globals.m_iInPlaceSubItem = iSubItem; { switch (iSubItem) { case PLAYLIST_TITLE: SendMessage(windows.wnd_playlist_IPEdit, WM_SETTEXT, 0L, (LPARAM)CPLI_GetTrackName(hClickedItem)); if (!options.support_id3v2) SendMessage(windows.wnd_playlist_IPEdit, EM_LIMITTEXT, 30, 0); break; case PLAYLIST_ARTIST: SendMessage(windows.wnd_playlist_IPEdit, WM_SETTEXT, 0L, (LPARAM)CPLI_GetArtist(hClickedItem)); if (!options.support_id3v2) SendMessage(windows.wnd_playlist_IPEdit, EM_LIMITTEXT, 30, 0); break; case PLAYLIST_ALBUM: SendMessage(windows.wnd_playlist_IPEdit, WM_SETTEXT, 0L, (LPARAM)CPLI_GetAlbum(hClickedItem)); if (!options.support_id3v2) SendMessage(windows.wnd_playlist_IPEdit, EM_LIMITTEXT, 30, 0); break; case PLAYLIST_YEAR: SendMessage(windows.wnd_playlist_IPEdit, WM_SETTEXT, 0L, (LPARAM)CPLI_GetYear(hClickedItem)); if (!options.support_id3v2) SendMessage(windows.wnd_playlist_IPEdit, EM_LIMITTEXT, 4, 0); break; case PLAYLIST_TRACKNUM: { char cTrackNum[33]; unsigned char iTrackNum; iTrackNum = CPLI_GetTrackNum(hClickedItem); if (iTrackNum != CIC_INVALIDTRACKNUM && iTrackNum != 0) SendMessage(windows.wnd_playlist_IPEdit, WM_SETTEXT, 0L, (LPARAM)_itoa(iTrackNum, cTrackNum, 10)); } SendMessage(windows.wnd_playlist_IPEdit, EM_LIMITTEXT, 3, 0); break; case PLAYLIST_COMMENT: SendMessage(windows.wnd_playlist_IPEdit, WM_SETTEXT, 0L, (LPARAM)CPLI_GetComment(hClickedItem)); if (!options.support_id3v2) SendMessage(windows.wnd_playlist_IPEdit, EM_LIMITTEXT, 28, 0); break; case PLAYLIST_GENRE: SendMessage(windows.wnd_playlist_IPEdit, CB_SELECTSTRING, (WPARAM) - 1, (LPARAM)CPLI_GetGenre(hClickedItem)); break; } } globals.m_bIP_InhibitUpdates = FALSE; }
DWORD WINAPI CPI_Player__EngineEP(void* pCookie) { BOOL bTerminateThread = FALSE; HRESULT hr_ComState; CPs_PlayerContext playercontext; playercontext.m_pBaseEngineParams = (CPs_PlayEngine*)pCookie; playercontext.m_bOutputActive = FALSE; playercontext.m_iProportion_TrackLength = 0; playercontext.m_iLastSentTime_Secs = -1; playercontext.m_iLastSentTime_Proportion = -1; playercontext.m_iInternalVolume = 100; CP_CHECKOBJECT(playercontext.m_pBaseEngineParams); CP_TRACE0("Cooler Engine Startup"); hr_ComState = CoInitialize(NULL); // Initialise CoDecs CP_InitialiseCodec_MPEG(&playercontext.m_CoDecs[CP_CODEC_MPEG]); CP_InitialiseCodec_WAV(&playercontext.m_CoDecs[CP_CODEC_WAV]); CP_InitialiseCodec_OGG(&playercontext.m_CoDecs[CP_CODEC_OGG]); CP_InitialiseCodec_WinAmpPlugin(&playercontext.m_CoDecs[CP_CODEC_WINAMPPLUGIN]); // Initialise output module if (options.decoder_output_mode > CP_OUTPUT_last) options.decoder_output_mode = CP_OUTPUT_last; playercontext.m_dwCurrentOutputModule = options.decoder_output_mode; CPI_Player_Output_Initialise_WaveMapper(&playercontext.m_OutputModules[CP_OUTPUT_WAVE]); CPI_Player_Output_Initialise_DirectSound(&playercontext.m_OutputModules[CP_OUTPUT_DIRECTSOUND]); CPI_Player_Output_Initialise_File(&playercontext.m_OutputModules[CP_OUTPUT_FILE]); playercontext.m_pCurrentOutputModule = &playercontext.m_OutputModules[playercontext.m_dwCurrentOutputModule]; // Initialise EQ CPI_Player_Equaliser_Initialise_Basic(&playercontext.m_Equaliser); { CPs_PlayEngine* player = (CPs_PlayEngine*)pCookie; player->m_pContext = &playercontext; } // Initialise USER32.DLL for this thread { MSG msgDummy; PeekMessage(&msgDummy, 0, WM_USER, WM_USER, PM_NOREMOVE); // Signal this thread ready for input SetEvent(playercontext.m_pBaseEngineParams->m_hEvtThreadReady); } do { // Process any pending messages BOOL bForceRefill = FALSE; MSG msg; DWORD dwWaitResult; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Decode engine message switch (msg.message) { case CPTM_QUIT: bTerminateThread = TRUE; break; case CPTM_OPENFILE: { char* pcFilename = (char*)msg.wParam; // If there is another pending openfile then ignore this one // This helps when this thread is non responsive (on an http connect for example) // and the user is hammering the hell out of the play button (as I always // do) - this will cause a number of open/closes to be placed into the // message queue which will tie up this thread for ages!! MSG msg2; if (PeekMessage(&msg2, NULL, CPTM_OPENFILE, CPTM_OPENFILE, PM_NOREMOVE) == FALSE) { CPs_CoDecModule* pNewCoDec; // If there is a CoDec playing then shut it down if (playercontext.m_pCurrentOutputModule->m_pCoDec) { playercontext.m_pCurrentOutputModule->m_pCoDec->CloseFile(playercontext.m_pCurrentOutputModule->m_pCoDec); playercontext.m_pCurrentOutputModule->m_pCoDec = NULL; } CP_TRACE1("Openfile \"%s\"", pcFilename); pNewCoDec = OpenCoDec(&playercontext, pcFilename); // If the open failed then request a new stream from the interface if (pNewCoDec == NULL) { PostMessage(playercontext.m_pBaseEngineParams->m_hWndNotify, CPNM_PLAYERSTATE, (WPARAM)cppsEndOfStream, 0); } // Check the file's format - if the sample rate, nChannels or sample size has changed // then clear the current output and shutdown output device (this will cause a gap // - but only when the format changes) else if (playercontext.m_bOutputActive == TRUE) { CPs_FileInfo FileInfo; pNewCoDec->GetFileInfo(pNewCoDec, &FileInfo); if (FileInfo.m_iFreq_Hz != playercontext.m_iOpenDevice_Freq_Hz || FileInfo.m_bStereo != playercontext.m_bOpenDevice_Stereo || FileInfo.m_b16bit != playercontext.m_bOpenDevice_16bit) { CP_TRACE0("Stream format changes - clearing stream"); EmptyOutputStream(&playercontext); StartPlay(pNewCoDec, &playercontext); bForceRefill = TRUE; } } playercontext.m_pCurrentOutputModule->m_pCoDec = pNewCoDec; } #ifdef _DEBUG else { CP_TRACE1("Openfile of \"%s\" ignored due to other opens in the queue", pcFilename); } #endif // Cleanup free(pcFilename); } break; case CPTM_SEEK: if (playercontext.m_bOutputActive == TRUE) { // Ignore message if there is another on it's way! MSG msg2; if (PeekMessage(&msg2, NULL, CPTM_SEEK, CPTM_SEEK, PM_NOREMOVE) == FALSE) { if (playercontext.m_pCurrentOutputModule->m_pCoDec) playercontext.m_pCurrentOutputModule->m_pCoDec->Seek(playercontext.m_pCurrentOutputModule->m_pCoDec, (int)msg.wParam, (int)msg.lParam); playercontext.m_pCurrentOutputModule->Flush(playercontext.m_pCurrentOutputModule); bForceRefill = TRUE; } } // FALLTHROUGH - to let coolplayer know playing has resumed (bugfix from seeking when paused) */ case CPTM_PLAY: if (playercontext.m_pCurrentOutputModule->m_pCoDec) { // If we don't have an output stage - initialise one now if (playercontext.m_bOutputActive == FALSE) { StartPlay(playercontext.m_pCurrentOutputModule->m_pCoDec, &playercontext); bForceRefill = TRUE; } playercontext.m_pCurrentOutputModule->SetPause(playercontext.m_pCurrentOutputModule, FALSE); PostMessage(playercontext.m_pBaseEngineParams->m_hWndNotify, CPNM_PLAYERSTATE, (WPARAM)cppsPlaying, 0); playercontext.m_iLastSentTime_Secs = -1; playercontext.m_iLastSentTime_Proportion = -1; UpdateProgress(&playercontext); } break; case CPTM_STOP: if (playercontext.m_pCurrentOutputModule->m_pCoDec) { playercontext.m_pCurrentOutputModule->m_pCoDec->CloseFile(playercontext.m_pCurrentOutputModule->m_pCoDec); playercontext.m_pCurrentOutputModule->m_pCoDec = NULL; } if (playercontext.m_bOutputActive == TRUE) { playercontext.m_bOutputActive = FALSE; playercontext.m_pCurrentOutputModule->Uninitialise(playercontext.m_pCurrentOutputModule); } PostMessage(playercontext.m_pBaseEngineParams->m_hWndNotify, CPNM_PLAYERSTATE, (WPARAM)cppsStopped, 0); break; case CPTM_PAUSE: CP_TRACE0("Pause"); if (playercontext.m_bOutputActive == TRUE) playercontext.m_pCurrentOutputModule->SetPause(playercontext.m_pCurrentOutputModule, TRUE); PostMessage(playercontext.m_pBaseEngineParams->m_hWndNotify, CPNM_PLAYERSTATE, (WPARAM)cppsPaused, 0); break; case CPTM_SETPROGRESSTRACKLENGTH: playercontext.m_iProportion_TrackLength = (int)msg.wParam; break; case CPTM_SENDSYNCCOOKIE: PostMessage(playercontext.m_pBaseEngineParams->m_hWndNotify, CPNM_SYNCCOOKIE, msg.wParam, 0); break; case CPTM_BLOCKMSGUNTILENDOFSTREAM: EmptyOutputStream(&playercontext); break; case CPTM_ENUMOUTPUTDEVICES: EnumOutputDevices(&playercontext); break; case CPTM_SETEQSETTINGS: { MSG msg2; CPs_EQSettings* pEQ = (CPs_EQSettings*)msg.wParam; // If there is another pending EQ message do no processing for this one (try to reduce noise) if (PeekMessage(&msg2, NULL, CPTM_SETEQSETTINGS, CPTM_OPENFILE, PM_NOREMOVE) == FALSE) { BOOL bEQEnableStateChanged; playercontext.m_Equaliser.ApplySettings(&playercontext.m_Equaliser, pEQ, &bEQEnableStateChanged); // Empty the buffers (this will cause a discontinuity in the music but at least // the EQ setting change will be immediate if (playercontext.m_bOutputActive == TRUE && playercontext.m_pCurrentOutputModule->OnEQChanged) playercontext.m_pCurrentOutputModule->OnEQChanged(playercontext.m_pCurrentOutputModule); } free(pEQ); } break; case CPTM_ONOUTPUTMODULECHANGE: { playercontext.m_dwCurrentOutputModule = options.decoder_output_mode; SetCurrentOutputModule(&playercontext, NULL, &bForceRefill); } break; case CPTM_ASSOCIATEFILEEXTENSIONS: AssociateFileExtensions(&playercontext); break; case CPTM_SETINTERNALVOLUME: playercontext.m_iInternalVolume = (int)msg.wParam; if (playercontext.m_bOutputActive == TRUE && playercontext.m_pCurrentOutputModule->SetInternalVolume) playercontext.m_pCurrentOutputModule->SetInternalVolume(playercontext.m_pCurrentOutputModule, playercontext.m_iInternalVolume); break; } } if (bTerminateThread) break; // Wait for either another message or a buffer expiry (if we have a player) if (playercontext.m_bOutputActive) { dwWaitResult = 0L; if (bForceRefill == FALSE) { if (playercontext.m_pCurrentOutputModule->m_evtBlockFree) dwWaitResult = MsgWaitForMultipleObjects(1, &playercontext.m_pCurrentOutputModule->m_evtBlockFree, FALSE, 1000, QS_POSTMESSAGE); else dwWaitResult = WAIT_OBJECT_0; } // If the buffer event is signaled then request a refill if (bForceRefill == TRUE || dwWaitResult == WAIT_OBJECT_0) { if (playercontext.m_pCurrentOutputModule->m_pCoDec) { playercontext.m_pCurrentOutputModule->RefillBuffers(playercontext.m_pCurrentOutputModule); if (playercontext.m_pCurrentOutputModule->m_pCoDec == NULL) { // Tell UI that we need another file to play PostMessage(playercontext.m_pBaseEngineParams->m_hWndNotify, CPNM_PLAYERSTATE, (WPARAM)cppsEndOfStream, 0); } else UpdateProgress(&playercontext); } // If output has finished everything that it was doing - close the engine else if (playercontext.m_pCurrentOutputModule->IsOutputComplete(playercontext.m_pCurrentOutputModule) == TRUE) { playercontext.m_bOutputActive = FALSE; playercontext.m_pCurrentOutputModule->Uninitialise(playercontext.m_pCurrentOutputModule); PostMessage(playercontext.m_pBaseEngineParams->m_hWndNotify, CPNM_PLAYERSTATE, (WPARAM)cppsStopped, 0); } } } else { WaitMessage(); } } while (bTerminateThread == FALSE); // Clean up output (if it's still active) if (playercontext.m_pCurrentOutputModule->m_pCoDec) { playercontext.m_pCurrentOutputModule->m_pCoDec->CloseFile(playercontext.m_pCurrentOutputModule->m_pCoDec); playercontext.m_pCurrentOutputModule->m_pCoDec = NULL; } if (playercontext.m_bOutputActive == TRUE) playercontext.m_pCurrentOutputModule->Uninitialise(playercontext.m_pCurrentOutputModule); // Clean up modules playercontext.m_Equaliser.Uninitialise(&playercontext.m_Equaliser); CleanupCoDecs(&playercontext); if (hr_ComState == S_OK) CoUninitialize(); CP_TRACE0("Cooler Engine terminating"); return 0; }
unsigned int _stdcall EP_FillerThread(void* _pContext) { CPs_BufferFillerContext* pContext = (CPs_BufferFillerContext*)_pContext; HINTERNET hInternet; HINTERNET hURLStream; DWORD dwTimeout; BOOL bStreamComplete = FALSE; INTERNET_BUFFERS internetbuffer; BYTE bReadBuffer[CIC_READCHUNKSIZE]; CP_CHECKOBJECT(pContext); PostMessage(pContext->m_hWndNotify, CPNM_SETSTREAMINGSTATE, (WPARAM)TRUE, (LPARAM)0); // Check that we can open this file hInternet = InternetOpen("CoolPlayer", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0L); if (hInternet == NULL) { pContext->m_pCircleBuffer->SetComplete(pContext->m_pCircleBuffer); CP_TRACE0("EP_FillerThread::NoInternetOpen"); return 0; } dwTimeout = 2000; InternetSetOption(hInternet, INTERNET_OPTION_CONNECT_TIMEOUT, &dwTimeout, sizeof(dwTimeout)); hURLStream = InternetOpenUrl(hInternet, pContext->m_pcFlexiURL, NULL, 0, INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE, 0); if (hURLStream == NULL) { InternetCloseHandle(hInternet); pContext->m_pCircleBuffer->SetComplete(pContext->m_pCircleBuffer); CP_TRACE1("EP_FillerThread::NoOpenURL %s", pContext->m_pcFlexiURL); return 0; } // Setup the internet buffer internetbuffer.dwStructSize = sizeof(internetbuffer); internetbuffer.Next = NULL; internetbuffer.lpcszHeader = NULL; internetbuffer.lpvBuffer = bReadBuffer; internetbuffer.dwBufferLength = CIC_READCHUNKSIZE; // Perform reading while (pContext->m_bTerminate == FALSE && bStreamComplete == FALSE) { BOOL bReadResult; // Is our circle buffer full? if (pContext->m_pCircleBuffer->GetFreeSize(pContext->m_pCircleBuffer) < CIC_READCHUNKSIZE) { Sleep(20); continue; } // Read in another chunk - if we don't get any data that's ok - we would rather poll the // buffers than just hang on the socket (so the stream can be shutdown if needed) internetbuffer.dwBufferLength = CIC_READCHUNKSIZE; bReadResult = InternetReadFileEx(hURLStream, &internetbuffer, IRF_NO_WAIT, 0); if (bReadResult == FALSE) bStreamComplete = TRUE; if (internetbuffer.dwBufferLength) { pContext->m_pCircleBuffer->Write(pContext->m_pCircleBuffer, internetbuffer.lpvBuffer, internetbuffer.dwBufferLength); PostMessage(pContext->m_hWndNotify, CPNM_SETSTREAMINGSTATE, (WPARAM)TRUE, (LPARAM)(pContext->m_pCircleBuffer->GetUsedSize(pContext->m_pCircleBuffer)*100) / CIC_STREAMBUFFERSIZE); } else Sleep(20); } InternetCloseHandle(hURLStream); InternetCloseHandle(hInternet); pContext->m_pCircleBuffer->SetComplete(pContext->m_pCircleBuffer); PostMessage(pContext->m_hWndNotify, CPNM_SETSTREAMINGSTATE, (WPARAM)FALSE, (LPARAM)0); CP_TRACE0("EP_FillerThread normal shutdown"); return 0; }