| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- /******************************************************************************
- |* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- |* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- |* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- |* PARTICULAR PURPOSE.
- |*
- |* Copyright 1995-2005 Nero AG. All Rights Reserved.
- |*-----------------------------------------------------------------------------
- |* PROJECT: Nero Plugin Manager Example
- |*
- |* FILE: WavSrc.cpp
- |*
- |* PURPOSE: Implementation of the wave source class
- ******************************************************************************/
- #include "stdafx.h"
- #include "WavSrc.h"
- // helper functions for file access
- #include "FileHelper.h"
- // IURLHolder implementation
- bool CWavSrc::SetURL(const char* szURL, IStatus** ppStatus)
- {
- RETURN_ERROR(AE_CallNotImplemented);
- }
- const char* CWavSrc::GetURL()
- {
- return m_csURL;
- }
- EURLType CWavSrc::GetType()
- {
- return URL_LocalFile;
- }
- // IProcess implementation
- bool CWavSrc::Start(IStatus** ppStatus)
- {
- if(NULL != ppStatus)
- {
- *ppStatus = NULL;
- }
- m_dwCurPos = 0;
- if(SetFilePointer(m_hFile, m_dwDataStart, 0, FILE_BEGIN) !=
- m_dwDataStart)
- {
- RETURN_ERROR(GetLastError());
- }
- m_bStarted = true;
- return true;
- }
- bool CWavSrc::End(IStatus** ppStatus)
- {
- if(NULL != ppStatus)
- {
- *ppStatus = NULL;
- }
- m_bStarted = false;
- return true;
- }
- bool CWavSrc::IsInProcess()
- {
- return m_bStarted;
- }
- // IAudioItem implementation
- bool CWavSrc::GetCreator(IAudioComponent** pCreator)
- {
- if(!pCreator)
- {
- ASSERT(FALSE);
- return false;
- }
- *pCreator = m_pCreator;
- (*pCreator)->AddRef();
- return true;
- }
- EAuxFlags CWavSrc::GetAuxFlags()
- {
- return SRC_FLAGS;
- }
- void CWavSrc::SetAuxFlags(EAuxFlags flags)
- {
- // Nothing to do here
- }
- // IAudioSource implementation
- SWavFormat CWavSrc::GetRawFormat()
- {
- SWavFormat format;
- format.m_iSamplesPerSecond= m_format.wf.nSamplesPerSec;
- format.m_iBitsPerSample = m_format.wBitsPerSample;
- format.m_iChannels = m_format.wf.nChannels;
- return format;
- }
- // iBufSize must contain the size in bytes of the buffer pointed by pBuf.
- bool CWavSrc::RawRead(BYTE* pBuf, int iBufSize, int* piRead,
- EAudioRawState& state,
- IStatus** ppStatus)
- {
- if(!(pBuf && iBufSize && piRead))
- {
- RETURN_ERROR(AE_InvalidParameter);
- }
- if(NULL != ppStatus)
- {
- *ppStatus = NULL;
- }
- state = ERS_None;
- if(m_dwCurPos >= m_dwDataLen)
- {
- state = ERS_EndOfFile;
- RETURN_ERROR(AE_EOF);
- }
- DWORD dwRead = 0;
- DWORD dwRemaining = m_dwDataLen - m_dwCurPos;
- if(iBufSize > (int)dwRemaining)
- {
- iBufSize = dwRemaining;
- state = ERS_EndOfFile;
- }
- if (!(ReadFile(m_hFile, pBuf, iBufSize, (DWORD*)piRead, NULL) && *piRead))
- {
- // That means that the file is over or
- // something is wrong, in any case
- // stopping the process
- m_dwCurPos = m_dwDataLen;
- }
- else
- {
- m_dwCurPos += *piRead;
- }
- return true;
- }
- // Returns free-form text string about the item.
- const char* CWavSrc::GetInfo()
- {
- if(m_csInfo.IsEmpty())
- {
- m_csInfo.Format("PCM Wav file. Format: %d, Channels: %d,"
- " Sample rate: %d, Bits per sample: %d",
- m_format.wf.wFormatTag,
- m_format.wf.nChannels,
- m_format.wf.nSamplesPerSec,
- m_format.wBitsPerSample);
- CString* pcsStrings[] =
- { &m_csArtist, &m_csTitle, &m_csCopyright, &m_csDate, &m_csComments };
- char* szarNames[5] =
- { "Artist", "Title", "Copyright", "Date", "Comments" };
- for(int i = 0; i < 5; i++)
- {
- CString* pcs = pcsStrings[i];
- if (pcs->IsEmpty())
- continue;
- m_csInfo += ",\r\n";
- CString csTemp;
- csTemp.Format("%s: %s", szarNames[i], (LPCTSTR)(*pcs));
- m_csInfo += csTemp;
- }
- }
- return m_csInfo;
- }
- // Returns the file duration in milliseconds.
- ULONGLONG CWavSrc::GetDuration()
- {
- return m_qwDuration;
- }
- // Returns RAW data length in bytes.
- ULONGLONG CWavSrc::GetRawLen()
- {
- return m_dwDataLen;
- }
- // ISeekable implementation
- bool CWavSrc::Seek(ULONGLONG pos, IStatus** ppStatus)
- {
- if(NULL == ppStatus)
- {
- *ppStatus = NULL;
- }
- DWORD dwLastPos = SetFilePointer(m_hFile, 0, 0, FILE_CURRENT);
- DWORD dwNewPos = (DWORD)(m_dwDataStart + pos * m_iBlockSize);
- bool bRetCode = false;
- if(SetFilePointer(m_hFile, dwNewPos, 0, FILE_BEGIN) != dwNewPos)
- {
- SetFilePointer(m_hFile, dwLastPos, 0, FILE_BEGIN);
- }
- else
- {
- m_dwCurPos = (DWORD)(pos * m_iBlockSize);
- bRetCode = true;
- }
- if((false == bRetCode) && (NULL != ppStatus))
- {
- *ppStatus = new CStatus(AE_SeekFailed);
- }
- return bRetCode;
- }
- ULONGLONG CWavSrc::GetPos()
- {
- return (m_dwCurPos / m_iBlockSize);
- }
- ULONGLONG CWavSrc::GetBlockSize()
- {
- return m_iBlockSize;
- }
- ULONGLONG CWavSrc::GetDataLength()
- {
- return (m_dwDataLen / m_iBlockSize);
- }
- // ISrcInfoViewerEditor implementation
- bool CWavSrc::GetCallback(ISrcInfoCallback** ppCB)
- {
- if(NULL == ppCB)
- {
- ASSERT(FALSE);
- return false;
- }
- *ppCB = m_pCallback;
- if(NULL != *ppCB)
- {
- (*ppCB)->AddRef();
- }
- return true;
- }
- void CWavSrc::SetCallback(ISrcInfoCallback* pNewCallback)
- {
- m_pCallback = pNewCallback;
- }
- bool CWavSrc::DoModal(IStatus** ppStatus)
- {
- CWavSrcInfoDlg dlg(this);
- m_pAdvInfoDlg = &dlg;
- dlg.DoModal();
- m_pAdvInfoDlg = NULL;
- return true;
- }
- bool CWavSrc::CloseModal(IStatus** ppStatus)
- {
- if(!(m_pAdvInfoDlg && IsWindow(m_pAdvInfoDlg->m_hWnd)))
- {
- return false;
- }
- m_pAdvInfoDlg->EndDialog(IDCANCEL);
- if (0 != IsWindow(m_pAdvInfoDlg->m_hWnd))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- bool CWavSrc::SaveDialogToObject(IStatus** ppStatus)
- {
- return false;
- }
- bool CWavSrc::SaveObjectToFile(IStatus** ppStatus)
- {
- return false;
- }
- bool CWavSrc::CanSaveObjectToFile()
- {
- return false;
- }
- // IInfoReader implementation
- const char* CWavSrc::GetTitle()
- {
- return m_csTitle;
- }
- const char* CWavSrc::GetArtist()
- {
- return m_csArtist;
- }
- const char* CWavSrc::GetAlbum()
- {
- return NULL;
- }
- const char* CWavSrc::GetYear()
- {
- return NULL;
- }
- const char* CWavSrc::GetGenre()
- {
- return NULL;
- }
- CWavSrc::CWavSrc(const char* szURL, IAudioComponent* pCreator,
- IStatus** ppStatus)
- : CAggregatable (0),
- m_pCreator (pCreator),
- m_hFile (INVALID_HANDLE_VALUE),
- m_bRiffChunk (FALSE),
- m_bWavChunk (FALSE),
- m_dwDataStart (0),
- m_dwDataLen (0),
- m_dwCurPos (0),
- m_iBlockSize (0),
- m_bOK (false),
- m_bStarted (false)
- {
- try
- {
- m_csURL = szURL;
- // CreateFile - create or open an object: Consoles, Communications resources
- // Directories (open only), Files etc.
- //
- // LPCTSTR lpFileName - file name
- // DWORD dwDesiredAccess - access mode
- // DWORD dwShareMode - share mode
- // LPSECURITY_ATTRIBUTES lpSecurityAttributes - [in] Pointer to a SECURITY_ATTRIBUTES
- // structure that determines whether the returned
- // handle can be inherited by child processes.
- // If lpSecurityAttributes is NULL, the handle cannot
- // be inherited.
- // DWORD dwCreationDisposition - how to create
- // DWORD dwFlagsAndAttributes - file attributes
- // HANDLE hTemplateFile - handle to template file
- m_hFile = CreateFile(szURL, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
- if(INVALID_HANDLE_VALUE == m_hFile )
- {
- if(NULL != ppStatus)
- {
- *ppStatus = new CStatus(GetLastError());
- }
- throw false;
- }
- // Trying to recognize the file
- DWORD dwRead = 0,
- dwFileSize = 0;
- try
- {
- ReadMMIO();
- }
- catch(BOOL )
- {
- // If we're here - something is wrong in this file
- // Sometimes files can contain some wrong information at the end,
- // but if the rest is OK we can accept such files.
- }
- // make sure that we are dealing with a valid file format
- if(false == ((INVALID_HANDLE_VALUE != m_hFile) &&
- (true == m_bRiffChunk) &&
- (true == m_bWavChunk) &&
- (0 != m_dwDataStart) &&
- (0 != m_dwDataLen)))
- {
- if(NULL != ppStatus)
- {
- *ppStatus = new CStatus(AE_BadFormat);
- }
- throw false;
- }
- // make sure that we are dealing with a valid wave format
- if(false == (((8 == m_format.wBitsPerSample) ||
- (16 == m_format.wBitsPerSample)) &&
- ((1 == m_format.wf.nChannels) ||
- (2 == m_format.wf.nChannels)) &&
-
- ((m_format.wf.nSamplesPerSec) >= 1000 &&
- (m_format.wf.nSamplesPerSec <= 100000))))
- {
- if(NULL != ppStatus)
- {
- *ppStatus = new CStatus(AE_BadFormat);
- }
- throw false;
- }
-
- // Calculating the file duration
- m_iBlockSize = (m_format.wBitsPerSample / BITS_PER_BYTE) *
- m_format.wf.nChannels;
- m_qwDuration = (ULONGLONG)m_dwDataLen * (ULONGLONG)1000 /
- m_format.wf.nAvgBytesPerSec;
- }
- catch(bool )
- {
- // Error occured
- return;
- }
- m_bOK = true;
- }
- CWavSrc::~CWavSrc()
- {
- if(m_hFile != INVALID_HANDLE_VALUE)
- {
- CloseHandle(m_hFile);
- }
- }
- HANDLE CWavSrc::GetFileHandle()
- {
- return m_hFile;
- }
- PCMWAVEFORMAT CWavSrc::GetWavSrcFormat()
- {
- return m_format;
- }
- HRESULT CWavSrc::ReadMMIO()
- {
- // Convert the CString URL to LPTSTR
- LPTSTR lpsz = new TCHAR[m_csURL.GetLength()+1];
- _tcscpy(lpsz, m_csURL);
- // MM I/O handle for the WAVE
- HMMIO hmmio;
- // Open the file with the appropriate multimedia function
- hmmio = mmioOpen(lpsz, NULL, MMIO_ALLOCBUF | MMIO_READ );
- // Free the temporay pointer
- delete lpsz;
- // Make sure that the file could be opened
-
- if( NULL != hmmio )
- {
- // Use in opening a WAVE file
- MMCKINFO ckRiff;
- // Use for subchunks
- MMCKINFO ck;
- // Search for the first chunk
- if( ( 0 != mmioDescend( hmmio, &ckRiff, NULL, 0 ) ) )
- {
- return E_FAIL;
- }
- // Make sure this is a valid wave file
-
- if( (ckRiff.ckid != FOURCC_RIFF) || (ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
- {
- return E_FAIL;
- }
- // If we got here, we can be sure that there is a riff chunk, and the type is WAVE
-
- m_bRiffChunk = true;
- m_bWavChunk = true;
- // Search the input file for for the 'fmt ' chunk.
- ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
- if( 0 != mmioDescend( hmmio, &ck, &ckRiff, MMIO_FINDCHUNK))
- {
- return E_FAIL;
- }
- // Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
- // if there are extra parameters at the end, we'll ignore them
- if( ck.cksize < (LONG) sizeof(PCMWAVEFORMAT))
- {
- return E_FAIL;
- }
- // Read the 'fmt ' chunk into m_format
- if( mmioRead( hmmio, (HPSTR) &m_format, sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
- {
- return E_FAIL;
- }
- if( m_format.wf.wFormatTag == WAVE_FORMAT_PCM )
- {
- // Seek to the data
- if( -1 == mmioSeek( hmmio, ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET))
- {
- return E_FAIL;
- }
- // Search the input file for the 'data' chunk.
- ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
- if( 0 != mmioDescend( hmmio, &ck, &ckRiff, MMIO_FINDCHUNK))
- {
- return E_FAIL;
- }
- // store offset and size of the data
- m_dwDataStart = ck.dwDataOffset;
- m_dwDataLen = ck.cksize;
- }
- else
- {
- // Wrong format
- return E_FAIL;
- }
- // Close the file
- mmioClose( hmmio, 0 );
- return S_OK;
- }
- else
- {
- // File could not be openend
- return E_FAIL;
- }
- }
|