void IF_ReleaseMouseCapture(CP_HINTERFACE hInterface) { CPs_InterfaceWindowState* pState; // Init pState = (CPs_InterfaceWindowState*)hInterface; CP_CHECKOBJECT(pState); pState->m_bMouseCaptured = FALSE; ReleaseCapture(); }
void IF_PostAppMessage(CP_HINTERFACE hInterface, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam) { CPs_InterfaceWindowState* pState; // Init pState = (CPs_InterfaceWindowState*)hInterface; CP_CHECKOBJECT(pState); CP_ASSERT(uiMessage >= WM_APP); PostMessage(pState->m_hWnd, uiMessage, wParam, lParam); }
BOOL CPSLOCAL_Read(CPs_InStream* pStream, void* pDestBuffer, const size_t iBytesToRead, size_t* piBytesRead) { DWORD bytes; BOOL reply; CPs_InStream_File* pContext = (CPs_InStream_File*)pStream->m_pModuleCookie; CP_CHECKOBJECT(pContext); reply = ReadFile(pContext->m_hFile, pDestBuffer, (DWORD)iBytesToRead, &bytes, 0); *piBytesRead = bytes; return reply; }
void CPP_OMFL_Flush(CPs_OutputModule* pModule) { #ifdef _DEBUG CPs_OutputContext_File* pContext = (CPs_OutputContext_File*)pModule->m_pModuleCookie; CP_CHECKOBJECT(pContext); // Stop any pending playing CP_ASSERT(CPP_OMFL_IsOutputComplete(pModule)); #endif }
void IF_SetMouseCapture(CP_HINTERFACE hInterface, wp_IF_onMouseMessage pfn_onMouseMove, wp_IF_onMouseMessage pfn_onMouseButton_LUp) { CPs_InterfaceWindowState* pState; // Init pState = (CPs_InterfaceWindowState*)hInterface; CP_CHECKOBJECT(pState); pState->m_bMouseCaptured = TRUE; pState->m_hndlr_onMouseMove = pfn_onMouseMove; pState->m_hndlr_onMouseButton_LUp = pfn_onMouseButton_LUp; SetCapture(pState->m_hWnd); }
void IF_SetVisible(CP_HINTERFACE hInterface, const BOOL bVisible) { CPs_InterfaceWindowState* pState; // Init pState = (CPs_InterfaceWindowState*)hInterface; CP_CHECKOBJECT(pState); if (bVisible) if (IsIconic(pState->m_hWnd)) ShowWindow(pState->m_hWnd, SW_RESTORE); ShowWindow(pState->m_hWnd, bVisible ? SW_SHOW : SW_HIDE); }
const CPs_SubFile* CP_FindFile(CP_COMPOSITEFILE hComposite, const char* pcFilename) { CPs_CompositeContext* pContext = (CPs_CompositeContext*)hComposite; const CPs_SubFile* pSubFile_Cursor; CP_CHECKOBJECT(pContext); // Search for subfile for (pSubFile_Cursor = pContext->m_pFirstSubFile; pSubFile_Cursor; pSubFile_Cursor = (const CPs_SubFile*)pSubFile_Cursor->m_pNext) { if (stricmp(pSubFile_Cursor->m_pcName, pcFilename) == 0) return pSubFile_Cursor; } return NULL; }
void CPSINET_Uninitialise(CPs_InStream* pStream) { CPs_InStream_Internet* pContext = (CPs_InStream_Internet*)pStream->m_pModuleCookie; CP_CHECKOBJECT(pContext); // Clear the thread pContext->m_pBufferFillContext->m_bTerminate = TRUE; WaitForSingleObject(pContext->m_hFillerThread, INFINITE); CloseHandle(pContext->m_hFillerThread); free(pContext->m_pBufferFillContext->m_pcFlexiURL); free(pContext->m_pBufferFillContext); // Free this context pContext->m_pCircleBuffer->Uninitialise(pContext->m_pCircleBuffer); free(pContext); free(pStream); }
void CPP_OMFL_SetPause(CPs_OutputModule* pModule, const BOOL bPause) { CPs_OutputContext_File* pContext = (CPs_OutputContext_File*)pModule->m_pModuleCookie; CP_CHECKOBJECT(pContext); if (!pContext->m_hFile) return; // Toggle pause state if (bPause == TRUE) pContext->m_bPaused = TRUE; else { pContext->m_bPaused = FALSE; SetEvent(pModule->m_evtBlockFree); } }
void CPP_OMFL_SetInternalVolume(CPs_OutputModule* pModule, const int iNewVolume) { CPs_OutputContext_File* pContext = (CPs_OutputContext_File*)pModule->m_pModuleCookie; int iNewVolume_DWORD; CP_CHECKOBJECT(pContext); if (!pContext->m_hFile) return; // Clip volume to word iNewVolume_DWORD = iNewVolume * 656; if (iNewVolume_DWORD > 0xFFFF) iNewVolume_DWORD = 0xFFFF; iNewVolume_DWORD |= (iNewVolume_DWORD << 16); }
unsigned int CircleGetFreeSpace(CPs_CircleBuffer* pCBuffer) { unsigned int iNumBytesFree; CP_CHECKOBJECT(pCBuffer); EnterCriticalSection(&pCBuffer->m_csCircleBuffer); if (pCBuffer->m_iWriteCursor < pCBuffer->m_iReadCursor) iNumBytesFree = (pCBuffer->m_iReadCursor - 1) - pCBuffer->m_iWriteCursor; else if (pCBuffer->m_iWriteCursor == pCBuffer->m_iReadCursor) iNumBytesFree = pCBuffer->m_iBufferSize; else iNumBytesFree = (pCBuffer->m_iReadCursor - 1) + (pCBuffer->m_iBufferSize - pCBuffer->m_iWriteCursor); LeaveCriticalSection(&pCBuffer->m_csCircleBuffer); return iNumBytesFree; }
void IF_RemoveAllSubparts(CP_HINTERFACE hInterface) { CPs_InterfaceWindowState* pState; CPs_InterfacePart* pSubPart_Cursor; CPs_InterfacePart* pSubPart_Next; // Init pState = (CPs_InterfaceWindowState*)hInterface; CP_CHECKOBJECT(pState); // Walk through list destroying subparts for (pSubPart_Cursor = pState->m_pFirstSubPart; pSubPart_Cursor; pSubPart_Cursor = pSubPart_Next) { pSubPart_Next = (CPs_InterfacePart*)pSubPart_Cursor->m_hNext; IP_Destroy(pSubPart_Cursor); } pState->m_pFirstSubPart = NULL; }
void CPP_OMFL_Uninitialise(CPs_OutputModule* pModule) { CPs_OutputContext_File* pContext = (CPs_OutputContext_File*)pModule->m_pModuleCookie; CP_CHECKOBJECT(pContext); CP_TRACE0("Wave out shutting down"); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); // If there is a File handle if (pContext->m_hFile) { // Stop any pending playing fclose(pContext->m_hFile); pContext->m_hFile = NULL; // Clean up CloseHandle(pModule->m_evtBlockFree); } free(pContext); pModule->m_pModuleCookie = NULL; }
void IF_AddSubPart_Indicator(CP_HINTERFACE hInterface, const char* pcName, const DWORD dwAlign, const RECT* prPosition) { CPs_InterfaceWindowState* pState; CPs_InterfacePart* pSubPart_Next; // Init pState = (CPs_InterfaceWindowState*)hInterface; CP_CHECKOBJECT(pState); // Add new head to list pSubPart_Next = pState->m_pFirstSubPart; // Setup new part pState->m_pFirstSubPart = IP_Create_Indicator(pcName); pState->m_pFirstSubPart->m_hNext = pSubPart_Next; pState->m_pFirstSubPart->m_hOwner = hInterface; pState->m_pFirstSubPart->m_dwAlign = dwAlign; pState->m_pFirstSubPart->m_bRectAlignMode = TRUE; pState->m_pFirstSubPart->m_rPosition = *prPosition; }
BOOL CircleBufferRead(CPs_CircleBuffer* pCBuffer, void* pDestBuffer, const unsigned int _iBytesToRead, unsigned int* pbBytesRead) { unsigned int iBytesToRead = _iBytesToRead; unsigned int iBytesRead = 0; DWORD dwWaitResult; BOOL bComplete = FALSE; CP_CHECKOBJECT(pCBuffer); while (iBytesToRead > 0 && bComplete == FALSE) { dwWaitResult = WaitForSingleObject(pCBuffer->m_evtDataAvailable, CIC_WAITTIMEOUT); if (dwWaitResult == WAIT_TIMEOUT) { CP_TRACE0("Circle buffer - did not fill in time!"); *pbBytesRead = iBytesRead; return FALSE; } EnterCriticalSection(&pCBuffer->m_csCircleBuffer); // Take what we can from the CBuffer if (pCBuffer->m_iReadCursor > pCBuffer->m_iWriteCursor) { unsigned int iChunkSize = pCBuffer->m_iBufferSize - pCBuffer->m_iReadCursor; if (iChunkSize > iBytesToRead) iChunkSize = iBytesToRead; // Perform the read memcpy((BYTE*)pDestBuffer + iBytesRead, pCBuffer->m_pBuffer + pCBuffer->m_iReadCursor, iChunkSize); iBytesRead += iChunkSize; iBytesToRead -= iChunkSize; pCBuffer->m_iReadCursor += iChunkSize; if (pCBuffer->m_iReadCursor >= pCBuffer->m_iBufferSize) pCBuffer->m_iReadCursor -= pCBuffer->m_iBufferSize; } if (iBytesToRead && pCBuffer->m_iReadCursor < pCBuffer->m_iWriteCursor) { unsigned int iChunkSize = pCBuffer->m_iWriteCursor - pCBuffer->m_iReadCursor; if (iChunkSize > iBytesToRead) iChunkSize = iBytesToRead; // Perform the read memcpy((BYTE*)pDestBuffer + iBytesRead, pCBuffer->m_pBuffer + pCBuffer->m_iReadCursor, iChunkSize); iBytesRead += iChunkSize; iBytesToRead -= iChunkSize; pCBuffer->m_iReadCursor += iChunkSize; } // Is there any more data to read if (pCBuffer->m_iReadCursor == pCBuffer->m_iWriteCursor) { if (pCBuffer->m_bComplete) bComplete = TRUE; } else SetEvent(pCBuffer->m_evtDataAvailable); LeaveCriticalSection(&pCBuffer->m_csCircleBuffer); } *pbBytesRead = iBytesRead; return bComplete ? FALSE : TRUE; }
void CPP_OMFL_RefillBuffers(CPs_OutputModule* pModule) { BOOL bMoreData; DWORD dwBufferLength = CPC_OUTPUTBLOCKSIZE; BYTE lpData[CPC_OUTPUTBLOCKSIZE]; CPs_OutputContext_File* pContext = (CPs_OutputContext_File*)pModule->m_pModuleCookie; CP_CHECKOBJECT(pContext); // Open a file out if (!pContext->m_hFile) { CPs_FileInfo pFileInfo; CP_HPLAYLISTITEM hCurrent = CPL_GetActiveItem(globals.m_hPlaylist); const char *pathname = CPLI_GetPath(hCurrent); char newpath[MAX_PATH]; int rec_rate; int rec_bits; UINT temp; WAVEFORMATEX wfs; char *dot; pModule->m_pCoDec->GetFileInfo(pModule->m_pCoDec, &pFileInfo); rec_rate = pFileInfo.m_iFreq_Hz; rec_bits = pFileInfo.m_b16bit == TRUE ? 16 : 8; // saving internet stream if (_strnicmp(pathname, CIC_HTTPHEADER, strlen(CIC_HTTPHEADER)) == 0) { strcpy(newpath, "Stream.wav"); pFileInfo.m_iFileLength_Secs = 0xffffffff; } else { // replace the extension with .wav strcpy(newpath, pathname); dot = strrchr(newpath, '.'); if (dot) *dot = '\0'; strcat(newpath, ".wav"); } // Trap error while (!pContext->m_hFile) { OPENFILENAME fn; char filefilter[] = "WAV files (*.wav)\0*.wav\0" "All Files (*.*)\0*.*\0"; BOOL returnval; fn.lStructSize = sizeof(OPENFILENAME); fn.hwndOwner = (HWND) GetWindowLong(windows.wnd_main, DWLP_USER); fn.hInstance = NULL; fn.lpstrFilter = filefilter; fn.lpstrCustomFilter = NULL; fn.nMaxCustFilter = 0; fn.nFilterIndex = 0; fn.lpstrFile = newpath; fn.nMaxFile = MAX_PATH * 200; fn.lpstrFileTitle = NULL; fn.nMaxFileTitle = 0; fn.lpstrInitialDir = options.last_used_directory; fn.lpstrTitle = NULL; fn.Flags = OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_EXPLORER; fn.nFileOffset = 0; fn.nFileExtension = 0; fn.lpstrDefExt = NULL; fn.lCustData = 0; fn.lpfnHook = NULL; fn.lpTemplateName = NULL; returnval = GetSaveFileName(&fn); if (!returnval) return; pContext->m_hFile = fopen(fn.lpstrFile, "wb"); if (pContext->m_hFile) break; } // Wave header stuff // prep wave format header wfs.wFormatTag = WAVE_FORMAT_PCM; wfs.nChannels = pFileInfo.m_bStereo == TRUE ? 2 : 1; wfs.nSamplesPerSec = rec_rate; wfs.nBlockAlign = (short)(rec_bits / 8 * wfs.nChannels); wfs.nAvgBytesPerSec = rec_rate * wfs.nBlockAlign; wfs.wBitsPerSample = rec_bits; wfs.cbSize = 0; // RIFF header block fwrite("RIFF", 4, 1, pContext->m_hFile); temp = sizeof(wfs) + 20 + (pFileInfo.m_iFileLength_Secs * wfs.nAvgBytesPerSec); fwrite(&temp, 4, 1, pContext->m_hFile); fwrite("WAVE", 4, 1, pContext->m_hFile); // 'fmt ' block fwrite("fmt ", 4, 1, pContext->m_hFile); temp = sizeof(wfs); fwrite(&temp, 4, 1, pContext->m_hFile); fwrite(&wfs, sizeof(wfs), 1, pContext->m_hFile); // 'data' block fwrite("data", 4, 1, pContext->m_hFile); temp = pFileInfo.m_iFileLength_Secs * wfs.nAvgBytesPerSec; fwrite(&temp, 4, 1, pContext->m_hFile); } // Scan ring buffer and fill any empty blocks - any blocks that become free // while this loop is running will retrigger the event - the worse that can // happen is that we enter this loop with no blocks free // Get block from CoDec and then just send it to the device (how easy is this!) bMoreData = pModule->m_pCoDec->GetPCMBlock(pModule->m_pCoDec, lpData, &dwBufferLength); // If there is EQ then apply it { // Note that the EQ module is initailised and uninitialsed by the engine CPs_EqualiserModule* pEQModule = (CPs_EqualiserModule*)pModule->m_pEqualiser; pEQModule->ApplyEQToBlock_Inplace(pEQModule, lpData, dwBufferLength); } if (dwBufferLength > 0) fwrite(lpData, dwBufferLength, 1, pContext->m_hFile); // Nothing to send if (bMoreData == FALSE) { pModule->m_pCoDec->CloseFile(pModule->m_pCoDec); pModule->m_pCoDec = NULL; if (pContext->m_hFile) fclose(pContext->m_hFile); pContext->m_hFile = NULL; } if (!pContext->m_bPaused) SetEvent(pModule->m_evtBlockFree); }
void IF_UpdateSubPartLayout(CP_HINTERFACE hInterface) { CPs_InterfaceWindowState* pState; CPs_InterfacePart* pSubPart_Cursor; // Init pState = (CPs_InterfaceWindowState*)hInterface; CP_CHECKOBJECT(pState); // Walk through list setting position for (pSubPart_Cursor = pState->m_pFirstSubPart; pSubPart_Cursor; pSubPart_Cursor = (CPs_InterfacePart*)pSubPart_Cursor->m_hNext) { if (pSubPart_Cursor->m_bRectAlignMode == TRUE) { // Set position // - left if (pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_LEFT) pSubPart_Cursor->m_rLocation.left = pSubPart_Cursor->m_rPosition.left; else { CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_RIGHT); pSubPart_Cursor->m_rLocation.left = pState->m_szWindowSize.cx - pSubPart_Cursor->m_rPosition.right - pSubPart_Cursor->m_rPosition.left; } // - right if (pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_RIGHT) pSubPart_Cursor->m_rLocation.right = pState->m_szWindowSize.cx - pSubPart_Cursor->m_rPosition.right; else { CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_LEFT); pSubPart_Cursor->m_rLocation.right = pSubPart_Cursor->m_rLocation.left + pSubPart_Cursor->m_rPosition.right; } // - top if (pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_TOP) pSubPart_Cursor->m_rLocation.top = pSubPart_Cursor->m_rPosition.top; else { // CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_BOTTOM); pSubPart_Cursor->m_rLocation.top = pState->m_szWindowSize.cy - pSubPart_Cursor->m_rPosition.bottom - pSubPart_Cursor->m_rPosition.top; } // - bottom if (pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_BOTTOM) pSubPart_Cursor->m_rLocation.bottom = pState->m_szWindowSize.cy - pSubPart_Cursor->m_rPosition.bottom; else { // CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_TOP); pSubPart_Cursor->m_rLocation.bottom = pSubPart_Cursor->m_rLocation.top + pSubPart_Cursor->m_rPosition.bottom; } } else { // Set position if (pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_LEFT) pSubPart_Cursor->m_rLocation.left = pSubPart_Cursor->m_ptOffset.x; else { CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_RIGHT); pSubPart_Cursor->m_rLocation.left = pState->m_szWindowSize.cx - pSubPart_Cursor->m_szSize.cx - pSubPart_Cursor->m_ptOffset.x; } pSubPart_Cursor->m_rLocation.right = pSubPart_Cursor->m_rLocation.left + pSubPart_Cursor->m_szSize.cx; if (pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_TOP) pSubPart_Cursor->m_rLocation.top = pSubPart_Cursor->m_ptOffset.y; else { CP_ASSERT(pSubPart_Cursor->m_dwAlign & CPC_COMMANDTARGET_ALIGN_BOTTOM); pSubPart_Cursor->m_rLocation.top = pState->m_szWindowSize.cy - pSubPart_Cursor->m_szSize.cy - pSubPart_Cursor->m_ptOffset.y; } pSubPart_Cursor->m_rLocation.bottom = pSubPart_Cursor->m_rLocation.top + pSubPart_Cursor->m_szSize.cy; } } }
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; }
BOOL CF_GetSubFile(CP_COMPOSITEFILE hComposite, const char* pcSubfilename, void** ppSubFile_Uncompressed, unsigned int* piSubFile_Length) { CPs_CompositeContext* pContext = (CPs_CompositeContext*)hComposite; const CPs_SubFile* pSubFile; DWORD dwCRC32; CP_CHECKOBJECT(pContext); pSubFile = CP_FindFile(hComposite, pcSubfilename); if (!pSubFile) { *ppSubFile_Uncompressed = NULL; *piSubFile_Length = 0; return FALSE; } // Create dest block *ppSubFile_Uncompressed = malloc(pSubFile->m_iUncompressedSize); *piSubFile_Length = pSubFile->m_iUncompressedSize; if (pSubFile->m_wMethod == CPC_PKFILE_METHOD_STORED) { memcpy(*ppSubFile_Uncompressed, pContext->m_pFileBase + pSubFile->m_iFileOffset, *piSubFile_Length); } else if (pSubFile->m_wMethod == CPC_PKFILE_METHOD_DEFLATED) { z_stream zStream; zStream.zalloc = Z_NULL; zStream.zfree = Z_NULL; zStream.opaque = Z_NULL; zStream.data_type = Z_BINARY; inflateInit2(&zStream, -15); // 15bit window (32Kb window size) (-ve to use an undocumented zLib "no zLib headers" mode) // Decompress zStream.next_out = (BYTE*) * ppSubFile_Uncompressed; zStream.avail_out = *piSubFile_Length; zStream.next_in = pContext->m_pFileBase + pSubFile->m_iFileOffset; zStream.avail_in = pSubFile->m_iCompressedSize; inflate(&zStream, Z_FINISH); // Cleanup inflateEnd(&zStream); } // Check CRC32 dwCRC32 = crc32(0, *ppSubFile_Uncompressed, *piSubFile_Length); if (dwCRC32 != pSubFile->m_dwCRC32) { // CRC32 does not match free(*ppSubFile_Uncompressed); *ppSubFile_Uncompressed = NULL; *piSubFile_Length = 0; return FALSE; } return TRUE; }
LRESULT CALLBACK exp_InterfaceWindowProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam) { CPs_InterfaceWindowState* pState; // Get the window's data object if (uiMessage == WM_NCCREATE) { HMODULE hModApplication; pState = (CPs_InterfaceWindowState*)((CREATESTRUCT*)lParam)->lpCreateParams; pState->m_hWnd = hWnd; SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pState); // Setup icons hModApplication = GetModuleHandle(NULL); SendMessage(hWnd, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)LoadIcon(hModApplication, MAKEINTRESOURCE(APP_ICON))); SendMessage(hWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)LoadIcon(hModApplication, MAKEINTRESOURCE(APP_ICON))); } else pState = (CPs_InterfaceWindowState*)GetWindowLong(hWnd, GWLP_USERDATA); // We get some messages before the window gets it's WM_NCCREATE!!! (just how bad is Windows eh???) if (!pState) return DefWindowProc(hWnd, uiMessage, wParam, lParam); CP_CHECKOBJECT(pState); // Message handlers switch (uiMessage) { case WM_MOUSEMOVE: { if (pState->m_bMouseCaptured) { if (pState->m_hndlr_onMouseMove) pState->m_hndlr_onMouseMove(pState, MAKEPOINTS(lParam), (SHORT)wParam); } else { CPs_InterfacePart* pHitSubPart; POINT ptMouse; ptMouse.x = (short)LOWORD(lParam); ptMouse.y = (short)HIWORD(lParam); pHitSubPart = IF_HitTestMouse(pState, &ptMouse); IF_SetFloatActiveSubPart(pState, pHitSubPart); } return 0; } // end WM_MOUSEMOVE case WM_LBUTTONDOWN: { CPs_InterfacePart* pHitSubPart; POINT ptMouse; ptMouse.x = (short)LOWORD(lParam); ptMouse.y = (short)HIWORD(lParam); pHitSubPart = IF_HitTestMouse(pState, &ptMouse); if (pHitSubPart && pHitSubPart->onMouseButton_LDown) { SetCapture(pState->m_hWnd); pState->m_pActiveSubpart = pHitSubPart; pHitSubPart->onMouseButton_LDown(pHitSubPart, MAKEPOINTS(lParam)); } return 0; } // end WM_LBUTTONDOWN case WM_LBUTTONUP: { if (pState->m_bMouseCaptured) { if (pState->m_hndlr_onMouseButton_LUp) pState->m_hndlr_onMouseButton_LUp(pState, MAKEPOINTS(lParam), (SHORT)wParam); } else { if (pState->m_pActiveSubpart) { ReleaseCapture(); if (pState->m_pActiveSubpart->onMouseButton_LUp) pState->m_pActiveSubpart->onMouseButton_LUp(pState->m_pActiveSubpart, MAKEPOINTS(lParam)); pState->m_pActiveSubpart = NULL; } } return 0; } // end WM_LBUTTONUP case WM_NCDESTROY: { IF_CleanupState(pState); break; } // end WM_NCDESTROY case WM_CREATE: { const CREATESTRUCT* pCS = (const CREATESTRUCT*)lParam; // Update size/pos cache pState->m_ptWindowPos.x = pCS->x; pState->m_ptWindowPos.y = pCS->y; pState->m_szWindowSize.cx = pCS->cx; pState->m_szWindowSize.cy = pCS->cy; // Reposition any subitems IF_UpdateSubPartLayout(pState); // Callback if (pState->m_hndlr_onCreate) { RECT rInitialPos; rInitialPos.left = 0; rInitialPos.top = 0; rInitialPos.right = pCS->cx; rInitialPos.bottom = pCS->cy; pState->m_hndlr_onCreate(pState, &rInitialPos); } IF_RebuildRegion(pState); return 0; } // end WM_CREATE case WM_DESTROY: { if (pState->m_hndlr_onDestroy) pState->m_hndlr_onDestroy(pState); IF_RemoveAllSubparts(pState); break; } // end WM_DESTROY case WM_NCHITTEST: { CPs_InterfacePart* pSubPart_Cursor; POINT ptMouse; ptMouse.x = (short)LOWORD(lParam) - pState->m_ptWindowPos.x; ptMouse.y = (short)HIWORD(lParam) - pState->m_ptWindowPos.y; // First perform hit testing on subparts for (pSubPart_Cursor = pState->m_pFirstSubPart; pSubPart_Cursor; pSubPart_Cursor = (CPs_InterfacePart*)pSubPart_Cursor->m_hNext) { if (PtInRect(&pSubPart_Cursor->m_rLocation, ptMouse) == TRUE) return HTCLIENT; } // If the window is sizable - perform hit testing on edges if (pState->m_dwStyle & CPC_INTERFACE_STYLE_RESIZING) { // Is the mouse inside the size bands // - top band if (ptMouse.y < CPC_SIZEBORDER) { // Are we in a corner // - left if (ptMouse.x < CPC_SIZEBORDER) return HTTOPLEFT; // - right else if (ptMouse.x > (pState->m_szWindowSize.cx - CPC_SIZEBORDER)) return HTTOPRIGHT; else return HTTOP; } // - bottom band else if (ptMouse.y > (pState->m_szWindowSize.cy - CPC_SIZEBORDER)) { // Are we in a corner // - left if (ptMouse.x < CPC_SIZEBORDER) return HTBOTTOMLEFT; // - right else if (ptMouse.x > (pState->m_szWindowSize.cx - CPC_SIZEBORDER)) return HTBOTTOMRIGHT; else return HTBOTTOM; } // - left band else if (ptMouse.x < CPC_SIZEBORDER) return HTLEFT; // - right band else if (ptMouse.x > (pState->m_szWindowSize.cx - CPC_SIZEBORDER)) return HTRIGHT; } // - return the caption so that the window is dragged return HTCAPTION; } // end WM_NCHITTEST case WM_WINDOWPOSCHANGED: { const WINDOWPOS* pWP = (const WINDOWPOS*)lParam; RECT rNewPos; BOOL bSizeChanged; rNewPos.left = pWP->x; rNewPos.right = pWP->x + pWP->cx; rNewPos.top = pWP->y; rNewPos.bottom = pWP->y + pWP->cy; bSizeChanged = (pWP->flags & SWP_NOSIZE) ? FALSE : TRUE; pState->m_ptWindowPos.x = pWP->x; pState->m_ptWindowPos.y = pWP->y; pState->m_szWindowSize.cx = pWP->cx; pState->m_szWindowSize.cy = pWP->cy; if (bSizeChanged) { IF_UpdateSubPartLayout(pState); IF_RebuildRegion(pState); } // Perform callback if (pState->m_hndlr_onPosChange) pState->m_hndlr_onPosChange(pState, &rNewPos, bSizeChanged); return 0; } // end WM_WINDOWPOSCHANGED case WM_NCCALCSIZE: { // We do not wish to have any window area lost to captions etc (also prevent the system // from preserving our window contents during a resize return WVR_REDRAW; } // end WM_NCCALCSIZE case WM_NCACTIVATE: return TRUE; case WM_NCPAINT: return 0; case WM_NCMOUSEMOVE: IF_SetFloatActiveSubPart(pState, NULL); return 0; case WM_MOUSELEAVE: IF_SetFloatActiveSubPart(pState, NULL); pState->m_bMouseLeaveEventSet = FALSE; return 0; case WM_CLOSE: { if (pState->m_hndlr_onClose) { pState->m_hndlr_onClose(pState); return 0; } break; } // end WM_CLOSE case WM_PAINT: { PAINTSTRUCT ps; CPs_DrawContext drawcontext; // Prepare for draw drawcontext.m_dcDraw = BeginPaint(hWnd, &ps); drawcontext.m_ptOffset.x = 0; drawcontext.m_ptOffset.y = 0; GetClipBox(drawcontext.m_dcDraw, &drawcontext.m_rClip); IF_PaintWindow(pState, &drawcontext); // Cleanup EndPaint(hWnd, &ps); return 0; } // end WM_PAINT case WM_ACTIVATE: { if (LOWORD(wParam) == WA_ACTIVE) SetFocus(hWnd); return 0; } // end WM_ACTIVATE case WM_SYSKEYDOWN: // FALLTHROUGH case WM_KEYDOWN: { if (pState->m_hndlr_onKeyDown) { const BOOL bAltIsDown = (GetAsyncKeyState(VK_MENU) & 0x8000) ? TRUE : FALSE; const BOOL bCtrlIsDown = (GetAsyncKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE; const BOOL bShiftIsDown = (GetAsyncKeyState(VK_SHIFT) & 0x8000) ? TRUE : FALSE; pState->m_hndlr_onKeyDown(pState, (unsigned int)wParam, bAltIsDown, bCtrlIsDown, bShiftIsDown); } return 0; } // end WM_KEYDOWN case WM_DROPFILES: { if (pState->m_hndlr_onDropFiles) pState->m_hndlr_onDropFiles(pState, (HDROP)wParam); return 0; } // end WM_DROPFILES case WM_GETMINMAXINFO: { MINMAXINFO* pMinMaxInfo = (MINMAXINFO*)lParam; RECT rWorkArea; if (pfnGetMonitorInfo) { // Multimonitors are supported by this OS MONITORINFO mi; HMONITOR hmon = pfnMonitorFromWindow(pState->m_hWnd, MONITOR_DEFAULTTOPRIMARY); mi.cbSize = sizeof(mi); pfnGetMonitorInfo(hmon, &mi); // Get the work area of this monitor - as an offset from this monitors virtual space rWorkArea.left = mi.rcWork.left - mi.rcMonitor.left; rWorkArea.right = mi.rcWork.right - mi.rcMonitor.left; rWorkArea.top = mi.rcWork.top - mi.rcMonitor.top; rWorkArea.bottom = mi.rcWork.bottom - mi.rcMonitor.top; } else { // Single monitor only OS SystemParametersInfo(SPI_GETWORKAREA, 0, &rWorkArea, 0); } pMinMaxInfo->ptMinTrackSize.x = pState->m_szMinSize.cx; pMinMaxInfo->ptMinTrackSize.y = pState->m_szMinSize.cy; pMinMaxInfo->ptMaxPosition.x = rWorkArea.left; pMinMaxInfo->ptMaxPosition.y = rWorkArea.top; pMinMaxInfo->ptMaxSize.x = rWorkArea.right - rWorkArea.left; pMinMaxInfo->ptMaxSize.y = rWorkArea.bottom - rWorkArea.top; pMinMaxInfo->ptMaxTrackSize.x = pMinMaxInfo->ptMaxSize.x; pMinMaxInfo->ptMaxTrackSize.y = pMinMaxInfo->ptMaxSize.y; return 0; } // end WM_GETMINMAXINFO case WM_SETFOCUS: { if (pState->m_hndlr_onFocus) pState->m_hndlr_onFocus(pState, TRUE); return 0; } // end WM_SETFOCUS case WM_KILLFOCUS: { if (pState->m_hndlr_onFocus) pState->m_hndlr_onFocus(pState, FALSE); return 0; } // end WM_KILLFOCUS case WM_COMMAND: { if (pState->m_hndlr_onCommandMessage) pState->m_hndlr_onCommandMessage(pState, wParam, lParam); return 0; } // end WM_COMMAND } // Route message (to windows if it isn't handled) if (uiMessage >= WM_APP && pState->m_hndlr_onAppMessage) return pState->m_hndlr_onAppMessage(pState, uiMessage, wParam, lParam); return DefWindowProc(hWnd, uiMessage, wParam, lParam); }