Welcome to mirror list, hosted at ThFree Co, Russian Federation.

MpcAudioRenderer.h « MpcAudioRenderer « renderer « filters « src - github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 480da8cc415568f2b76a11a4a7a5e1bd7282dc79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * $Id$
 *
 * (C) 2009-2012 see Authors.txt
 *
 * This file is part of MPC-HC.
 *
 * MPC-HC is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * MPC-HC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include "BaseClasses/streams.h"
#include <dsound.h>

#include <MMReg.h>  //must be before other Wasapi headers
#include <strsafe.h>
#include <mmdeviceapi.h>
#include <avrt.h>
#include <audioclient.h>
#include <endpointvolume.h>
#include <FunctionDiscoveryKeys_devpkey.h>

#include "MpcAudioRendererSettingsWnd.h"
#include "SoundTouch/include/SoundTouch.h"

#define MpcAudioRendererName L"MPC Audio Renderer"

// REFERENCE_TIME time units per second and per millisecond
#define REFTIMES_PER_SEC        10000000
#define REFTIMES_PER_MILLISEC   10000

// if you get a compilation error on AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED,
// uncomment the #define below
#define AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED  AUDCLNT_ERR(0x019)

class __declspec(uuid("601D2A2B-9CDE-40bd-8650-0485E3522727"))
    CMpcAudioRenderer : public CBaseRenderer
    , public IBasicAudio
    , public ISpecifyPropertyPages2
    , public IMpcAudioRendererFilter
{
public:
    CMpcAudioRenderer(LPUNKNOWN punk, HRESULT* phr);
    virtual ~CMpcAudioRenderer();

    static const AMOVIESETUP_FILTER sudASFilter;

    HRESULT                 CheckInputType(const CMediaType* mtIn);
    virtual HRESULT         CheckMediaType(const CMediaType* pmt);
    virtual HRESULT         DoRenderSample(IMediaSample* pMediaSample);
    virtual void            OnReceiveFirstSample(IMediaSample* pMediaSample);
    BOOL                    ScheduleSample(IMediaSample* pMediaSample);
    virtual HRESULT         SetMediaType(const CMediaType* pmt);
    virtual HRESULT         CompleteConnect(IPin* pReceivePin);

    HRESULT EndOfStream(void);


    DECLARE_IUNKNOWN

    STDMETHODIMP                NonDelegatingQueryInterface(REFIID riid, void** ppv);

    // === IMediaFilter
    STDMETHOD(Run)(REFERENCE_TIME tStart);
    STDMETHOD(Stop)();
    STDMETHOD(Pause)();

    // === IDispatch (pour IBasicAudio)
    STDMETHOD(GetTypeInfoCount)(UINT* pctinfo);
    STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo);
    STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid);
    STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr);

    // === IBasicAudio
    STDMETHOD(put_Volume)(long lVolume);
    STDMETHOD(get_Volume)(long* plVolume);
    STDMETHOD(put_Balance)(long lBalance);
    STDMETHOD(get_Balance)(long* plBalance);

    // === ISpecifyPropertyPages2
    STDMETHODIMP                GetPages(CAUUID* pPages);
    STDMETHODIMP                CreatePage(const GUID& guid, IPropertyPage** ppPage);

    // === IMpcAudioRendererFilter
    STDMETHODIMP                Apply();
    STDMETHODIMP                SetWasapiMode(BOOL nValue);
    STDMETHODIMP_(BOOL)         GetWasapiMode();
    STDMETHODIMP                SetMuteFastForward(BOOL nValue);
    STDMETHODIMP_(BOOL)         GetMuteFastForward();
    STDMETHODIMP                SetSoundDevice(CString nValue);
    STDMETHODIMP_(CString)      GetSoundDevice();

    // CMpcAudioRenderer
private:

    HRESULT                 DoRenderSampleDirectSound(IMediaSample* pMediaSample);

    HRESULT                 InitCoopLevel();
    HRESULT                 ClearBuffer();
    HRESULT                 CreateDSBuffer();
    HRESULT                 GetReferenceClockInterface(REFIID riid, void** ppv);
    HRESULT                 WriteSampleToDSBuffer(IMediaSample* pMediaSample, bool* looped);

    LPDIRECTSOUND8          m_pDS;
    LPDIRECTSOUNDBUFFER     m_pDSBuffer;
    DWORD                   m_dwDSWriteOff;
    WAVEFORMATEX*            m_pWaveFileFormat;
    int                     m_nDSBufSize;
    CBaseReferenceClock*    m_pReferenceClock;
    double                  m_dRate;
    long                    m_lVolume;
    soundtouch::SoundTouch* m_pSoundTouch;
    CCritSec                m_csProps;

    // CMpcAudioRenderer WASAPI methods
    HRESULT                 GetAvailableAudioDevices(IMMDeviceCollection** ppMMDevices);
    HRESULT                 GetAudioDevice(IMMDevice** ppMMDevice);
    HRESULT                 CreateAudioClient(IMMDevice* pMMDevice, IAudioClient** ppAudioClient);
    HRESULT                 InitAudioClient(WAVEFORMATEX* pWaveFormatEx, IAudioClient* pAudioClient, IAudioRenderClient** ppRenderClient);
    HRESULT                 CheckAudioClient(WAVEFORMATEX* pWaveFormatEx);
    bool                    CheckFormatChanged(WAVEFORMATEX* pWaveFormatEx, WAVEFORMATEX** ppNewWaveFormatEx);
    HRESULT                 DoRenderSampleWasapi(IMediaSample* pMediaSample);
    HRESULT                 GetBufferSize(WAVEFORMATEX* pWaveFormatEx, REFERENCE_TIME* pHnsBufferPeriod);


    // WASAPI variables
    bool                    m_useWASAPI;
    bool                    m_useWASAPIAfterRestart;
    bool                    m_bMuteFastForward;
    CString                 m_csSound_Device;
    IMMDevice*               pMMDevice;
    IAudioClient*            pAudioClient;
    IAudioRenderClient*      pRenderClient;
    UINT32                  nFramesInBuffer;
    REFERENCE_TIME          hnsPeriod, hnsActualDuration;
    HANDLE                  hTask;
    CCritSec                m_csCheck;
    UINT32                  bufferSize;
    bool                    isAudioClientStarted;
    DWORD                   lastBufferTime;

    // AVRT.dll (Vista or greater
    typedef HANDLE(__stdcall* PTR_AvSetMmThreadCharacteristicsW)(LPCWSTR TaskName, LPDWORD TaskIndex);
    typedef BOOL (__stdcall* PTR_AvRevertMmThreadCharacteristics)(HANDLE AvrtHandle);

    PTR_AvSetMmThreadCharacteristicsW       pfAvSetMmThreadCharacteristicsW;
    PTR_AvRevertMmThreadCharacteristics     pfAvRevertMmThreadCharacteristics;

};