예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
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;
}