我在COM中实现对一个音频文件的编码,我想在编码过程中向外界发送编码进度的消息,以便外面的挑用者在进度条上实现相应编码进度。
请问大家,如何在内部发送(用的是SDK编写COM,不是ATL。)?
外界又如何接收?
谢谢

解决方案 »

  1.   

    呵呵,这就是COM的连接点存在的原因了吧
    当COM中的变量改变的时候COM自动通知客户!
    找个COM连接点的例子看看吧!
      

  2.   

    参考:
    http://www.vchelp.net/itbookreview/view_paper.asp?paper_id=798http://www.yesky.com/20020322/1603133.shtmlhttp://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/vccore/html/vctskImplementingConnectionPoint.asphttp://blog.csdn.net/showman/archive/2001/05/10/9162.aspx
      

  3.   

    http://comcamp.myrice.com/techarticles/com/2001.htm
      

  4.   

    BOOL CAudioUtil::AddFile(BSTR lpFileName, __int64 llStartTime, __int64 llStopTime, __int64 llBegin)
    {
    // TODO: Add your implementation code here
    HRESULT hr; llStartTime = MS_TO_UNITS(llStartTime);
    JIZ(GetAudioLength(lpFileName, m_FileAudioLength[m_FileCount]));
    if (abs(llStopTime -0)<1E-6)//  
    {
    llStopTime = m_FileAudioLength[m_FileCount];
    }else
    {
    llStopTime = MS_TO_UNITS(llStopTime);
    }m_FileAudioLength[m_FileCount]=llStopTime-llStartTime;//; CComPtr<IAMTimelineObj> pSourceObj;
    JIF(m_pTimeline->CreateEmptyNode(&pSourceObj, TIMELINE_MAJOR_TYPE_SOURCE));
    JIF(pSourceObj->SetStartStop(llBegin , llBegin + llStopTime-llStartTime));//yanglei  llBegin + llStartTime, llBegin + llStopTime
    CComQIPtr<IAMTimelineSrc, &IID_IAMTimelineSrc> pSourceSrc(pSourceObj);
    JIF(pSourceSrc->SetMediaName(lpFileName));
    JIF(pSourceSrc->SetMediaTimes(llStartTime, llStopTime));//yanglei JIF( m_Track->SrcAdd(pSourceObj) ); m_Sources[m_FileCount] = pSourceObj;//
    m_FileTiimeline[m_FileCount][0] = llBegin + llStartTime;
    m_FileTiimeline[m_FileCount][1] = llBegin + llStopTime-llStartTime;
        if(m_FileTiimeline[m_FileCount][1] > m_TotalTime) 
    m_TotalTime = m_FileTiimeline[m_FileCount][1];
    m_FileCount ++; return TRUE;
    }BOOL CAudioUtil::OutputFile(BSTR lpOutFile, DWORD dwSampRate)
    {
    // TODO: Add your implementation code here
    HRESULT hr; CComPtr<IRenderEngine> m_pRenderEngine;
    JIF(m_pRenderEngine.CoCreateInstance(CLSID_RenderEngine, NULL, CLSCTX_INPROC_SERVER)); JIF(m_pRenderEngine->SetTimelineObject(m_pTimeline));
    JIF(m_pRenderEngine->ConnectFrontEnd());
    JIF(m_pRenderEngine->GetFilterGraph(&m_pTGBuilder)); CComPtr<IPin>pin1;
    m_pRenderEngine->GetGroupOutputPin(0, &pin1); // ACM Wrapper
    CComPtr<IBaseFilter> pACMWrapper;
    JIF(pACMWrapper.CoCreateInstance(CLSID_ACMWrapper, NULL, CLSCTX_INPROC_SERVER));
    JIF(m_pTGBuilder->AddFilter(pACMWrapper, L"ACM Wrapper")); CComPtr<IPin> pin2;
    JIZ(GetPin(pACMWrapper, PINDIR_INPUT, pin2));
    JIF(m_pTGBuilder->Connect(pin1, pin2)); CComPtr<IPin> pin3;
    JIZ(GetPin(pACMWrapper, PINDIR_OUTPUT, pin3));
    JIZ(SetPinSampRate(pin3, dwSampRate)); // Wave Dest
    CComPtr<IBaseFilter> pWaveDst;
    JIF(pWaveDst.CoCreateInstance(CLSID_WavDest, NULL, CLSCTX_INPROC_SERVER));
    JIF(m_pTGBuilder->AddFilter(pWaveDst, L"Wave Dest")); CComPtr<IPin> pin4;
    JIZ(GetPin(pWaveDst, PINDIR_INPUT, pin4));
    JIF(m_pTGBuilder->Connect(pin3, pin4));
    CComPtr<IPin> pin5;
    JIZ(GetPin(pWaveDst, PINDIR_OUTPUT, pin5)); // File write
    CComPtr<IBaseFilter> pFileWrite;
    JIF(pFileWrite.CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER));
    JIF(m_pTGBuilder->AddFilter(pFileWrite, L"File write")); CComQIPtr<IFileSinkFilter, &IID_IFileSinkFilter> pDes(pFileWrite);
    JIF(pDes->SetFileName(lpOutFile, NULL));
    pDes.Release();; CComPtr<IPin> pin6;
    JIZ(GetPin(pFileWrite, PINDIR_INPUT, pin6));
    JIF(m_pTGBuilder->Connect(pin5, pin6)); JIF(m_pTGBuilder->QueryInterface(IID_IMediaControl,(void**)&m_pControl)); JIF(m_pControl->Run()); CComPtr<IMediaEvent> pMediaEvent;
    JIF(m_pTGBuilder->QueryInterface(IID_IMediaEvent, (void **)&pMediaEvent)); // 事实上无法确定解码进度,只是一种估计值
    BOOL bReturn = TRUE;
    DWORD dwStreamLength = (DWORD)(UNITS_TO_MS(m_TotalTime) / 200);
    for(DWORD i = 0; i < dwStreamLength; i++)
    {
    long lEvCode;
    hr = pMediaEvent->WaitForCompletion(200, &lEvCode);
    switch(hr)
    {
    case E_ABORT:
    {
    DWORD nPercent = (i * 1000) / dwStreamLength;
    if (nPercent > 100) nPercent = 100;
    if (1 == FALSE)// yang
    {
    bReturn = FALSE;
    ShowRunMessage("Canceled by user .\n");
    goto lable_exit;
    }
    }
    continue; case S_OK:
    break; default:
    ShowRunMessage("Faild to WaitForCompletion, 0x%x\n", hr);
    bReturn = FALSE;
    goto lable_exit;
    } switch(lEvCode)
    {
    case EC_COMPLETE :
    goto lable_exit; case EC_ERRORABORT :
    case EC_USERABORT  :
    ShowRunMessage("Faild to WaitForCompletion, EvCode = 0x%x\n", lEvCode);
    bReturn = FALSE;
    goto lable_exit; default:
    ShowRunMessage("On WaitForCompletion, Unknow EvCode = 0x%x\n", lEvCode);
    break;
    }
    }lable_exit:
    m_pControl->Stop(); return bReturn;
      

  5.   

    // JIF(pTimeLineObj->SetStartStop(llBegin, llEnd));

        JIF(pTimeLineObj->SetStartStop(0, m_FileAudioLength[nIndex]));//4lei
    JIF(pTimeLineObj->SetSubObjectGUID(CLSID_AudMixer));
    // add the effect
    CComQIPtr<IAMTimelineEffectable , &IID_IAMTimelineEffectable> pTrackFable(m_Sources[nIndex]);
    JIF(pTrackFable->EffectInsBefore(pTimeLineObj, -1)); JIF(pTimeLineObj->SetSubObjectGUID(CLSID_AudMixer)); CComPtr<IPropertySetter> pVolSetter;
    JIF(pVolSetter.CoCreateInstance(CLSID_PropertySetter, NULL, CLSCTX_INPROC_SERVER));

    // the property name
    DEXTER_PARAM Param;
    Param.Name = L"Vol";
    Param.nValues = 3; // //4lei
    // Param.dispID=NULL;//4lei DEXTER_VALUE AudioValue[3];//4lei memset(&AudioValue[0], 0, sizeof(AudioValue[0]));
    VariantClear(&AudioValue[0].v);
    V_R8(&AudioValue[0].v) = 1;//4lei
    V_VT(&AudioValue[0].v) = VT_R8;
        

    memset( &AudioValue[1], 0, sizeof( AudioValue[1] ) );
    VariantClear( &AudioValue[1].v );
    V_R8( &AudioValue[1].v ) =1;//4lei
    V_VT( &AudioValue[1].v ) = VT_R8;
    memset( &AudioValue[2], 0, sizeof( AudioValue[2] ) );
    VariantClear( &AudioValue[2].v );
    V_R8( &AudioValue[2].v ) =0;//4lei
    V_VT( &AudioValue[2].v ) = VT_R8;

    AudioValue[0].rt = 0;
    AudioValue[1].rt = m_FileAudioLength[nIndex]-llBegin;//4lei
        AudioValue[2].rt = m_FileAudioLength[nIndex];//4lei AudioValue[1].dwInterp = DEXTERF_INTERPOLATE;

    AudioValue[2].dwInterp = DEXTERF_INTERPOLATE;//4lei JIF(pVolSetter->AddProp( Param, AudioValue ));
    JIF(pTimeLineObj->SetPropertySetter( pVolSetter ));
    return TRUE;
    }
    BOOL SetPinSampRate(CComPtr<IPin> &pPin, DWORD dwSampRate)
    {
    HRESULT hr; CComQIPtr<IAMStreamConfig, &IID_IAMStreamConfig>pAMStreamCfg(pPin); WAVEFORMATEX wf;
    ZeroMemory(&wf, sizeof(wf));
    wf.nChannels = 2;
    wf.nSamplesPerSec = dwSampRate;
    wf.wBitsPerSample = 16;
    wf.nAvgBytesPerSec = dwSampRate * 2 * 2;
    wf.nBlockAlign = 4;
    wf.wFormatTag = WAVE_FORMAT_PCM; AM_MEDIA_TYPE mt;
    ZeroMemory(&mt, sizeof(mt));
    mt.majortype = MEDIATYPE_Audio;
    mt.subtype = MEDIASUBTYPE_PCM;
    mt.bFixedSizeSamples = TRUE;
    mt.lSampleSize = 4;
    mt.formattype = FORMAT_WaveFormatEx;
    mt.cbFormat = sizeof(WAVEFORMATEX);
    mt.pbFormat = (BYTE *)&wf; JIF(pAMStreamCfg->SetFormat(&mt)); return TRUE;
    }BOOL CAudioUtil::GetPin(CComPtr<IBaseFilter> &pFilter, PIN_DIRECTION PinDir, CComPtr<IPin> &pPin)
    {
    CComPtr<IEnumPins> pEnum;
    pFilter->EnumPins(&pEnum); while(pEnum->Next(1, &pPin, 0) == S_OK)
    {
    PIN_DIRECTION PinDirThis;
    pPin->QueryDirection(&PinDirThis);
    if (PinDir == PinDirThis)
    {
    return TRUE;
    }
    pPin = NULL;
    } return FALSE;
    }
    BOOL CAudioUtil::OutputFile(BSTR lpOutFile, DWORD dwSampRate)
    {
    // TODO: Add your implementation code here
    HRESULT hr; CComPtr<IRenderEngine> m_pRenderEngine;
    JIF(m_pRenderEngine.CoCreateInstance(CLSID_RenderEngine, NULL, CLSCTX_INPROC_SERVER)); JIF(m_pRenderEngine->SetTimelineObject(m_pTimeline));
    JIF(m_pRenderEngine->ConnectFrontEnd());
    JIF(m_pRenderEngine->GetFilterGraph(&m_pTGBuilder)); CComPtr<IPin>pin1;
    m_pRenderEngine->GetGroupOutputPin(0, &pin1); // ACM Wrapper
    CComPtr<IBaseFilter> pACMWrapper;
    JIF(pACMWrapper.CoCreateInstance(CLSID_ACMWrapper, NULL, CLSCTX_INPROC_SERVER));
    JIF(m_pTGBuilder->AddFilter(pACMWrapper, L"ACM Wrapper")); CComPtr<IPin> pin2;
    JIZ(GetPin(pACMWrapper, PINDIR_INPUT, pin2));
    JIF(m_pTGBuilder->Connect(pin1, pin2)); CComPtr<IPin> pin3;
    JIZ(GetPin(pACMWrapper, PINDIR_OUTPUT, pin3));
    JIZ(SetPinSampRate(pin3, dwSampRate)); // Wave Dest
    CComPtr<IBaseFilter> pWaveDst;
    JIF(pWaveDst.CoCreateInstance(CLSID_WavDest, NULL, CLSCTX_INPROC_SERVER));
    JIF(m_pTGBuilder->AddFilter(pWaveDst, L"Wave Dest")); CComPtr<IPin> pin4;
    JIZ(GetPin(pWaveDst, PINDIR_INPUT, pin4));
    JIF(m_pTGBuilder->Connect(pin3, pin4));
    CComPtr<IPin> pin5;
    JIZ(GetPin(pWaveDst, PINDIR_OUTPUT, pin5)); // File write
    CComPtr<IBaseFilter> pFileWrite;
    JIF(pFileWrite.CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER));
    JIF(m_pTGBuilder->AddFilter(pFileWrite, L"File write")); CComQIPtr<IFileSinkFilter, &IID_IFileSinkFilter> pDes(pFileWrite);
    JIF(pDes->SetFileName(lpOutFile, NULL));
    pDes.Release();; CComPtr<IPin> pin6;
    JIZ(GetPin(pFileWrite, PINDIR_INPUT, pin6));
    JIF(m_pTGBuilder->Connect(pin5, pin6)); JIF(m_pTGBuilder->QueryInterface(IID_IMediaControl,(void**)&m_pControl)); JIF(m_pControl->Run()); CComPtr<IMediaEvent> pMediaEvent;
    JIF(m_pTGBuilder->QueryInterface(IID_IMediaEvent, (void **)&pMediaEvent)); BOOL bReturn = TRUE;
    DWORD dwStreamLength = (DWORD)(UNITS_TO_MS(m_TotalTime) / 200);
    for(DWORD i = 0; i < dwStreamLength; i++)
    {
    long lEvCode;
    hr = pMediaEvent->WaitForCompletion(200, &lEvCode);
    switch(hr)
    {
    case E_ABORT:
    {
    DWORD nPercent = (i * 1000) / dwStreamLength;
    if (nPercent > 100) nPercent = 100;
    if (1 == FALSE)// 4
    {
    bReturn = FALSE;
    ShowRunMessage("Canceled by user .\n");
    goto lable_exit;
    }
    }
    continue; case S_OK:
    break; default:
    ShowRunMessage("Faild to WaitForCompletion, 0x%x\n", hr);
    bReturn = FALSE;
    goto lable_exit;
    } switch(lEvCode)
    {
    case EC_COMPLETE :
    goto lable_exit; case EC_ERRORABORT :
    case EC_USERABORT  :
    ShowRunMessage("Faild to WaitForCompletion, EvCode = 0x%x\n", lEvCode);
    bReturn = FALSE;
    goto lable_exit; default:
    ShowRunMessage("On WaitForCompletion, Unknow EvCode = 0x%x\n", lEvCode);
    break;
    }
    }lable_exit:
    m_pControl->Stop(); return bReturn;
    }